diff options
Diffstat (limited to 'source/blender/windowmanager/intern')
25 files changed, 20868 insertions, 20084 deletions
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index a05dce9d59a..7647e9f558f 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -57,59 +57,59 @@ #include "BKE_undo_system.h" #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif /* ****************************************************** */ -#define MAX_OP_REGISTERED 32 +#define MAX_OP_REGISTERED 32 void WM_operator_free(wmOperator *op) { #ifdef WITH_PYTHON - if (op->py_instance) { - /* do this first in case there are any __del__ functions or - * similar that use properties */ - BPY_DECREF_RNA_INVALIDATE(op->py_instance); - } + if (op->py_instance) { + /* do this first in case there are any __del__ functions or + * similar that use properties */ + BPY_DECREF_RNA_INVALIDATE(op->py_instance); + } #endif - if (op->ptr) { - op->properties = op->ptr->data; - MEM_freeN(op->ptr); - } - - if (op->properties) { - IDP_FreeProperty(op->properties); - MEM_freeN(op->properties); - } - - if (op->reports && (op->reports->flag & RPT_FREE)) { - BKE_reports_clear(op->reports); - MEM_freeN(op->reports); - } - - if (op->macro.first) { - wmOperator *opm, *opmnext; - for (opm = op->macro.first; opm; opm = opmnext) { - opmnext = opm->next; - WM_operator_free(opm); - } - } - - MEM_freeN(op); + if (op->ptr) { + op->properties = op->ptr->data; + MEM_freeN(op->ptr); + } + + if (op->properties) { + IDP_FreeProperty(op->properties); + MEM_freeN(op->properties); + } + + if (op->reports && (op->reports->flag & RPT_FREE)) { + BKE_reports_clear(op->reports); + MEM_freeN(op->reports); + } + + if (op->macro.first) { + wmOperator *opm, *opmnext; + for (opm = op->macro.first; opm; opm = opmnext) { + opmnext = opm->next; + WM_operator_free(opm); + } + } + + MEM_freeN(op); } void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op) { - op = op->next; - while (op != NULL) { - wmOperator *op_next = op->next; - BLI_remlink(&wm->operators, op); - WM_operator_free(op); - op = op_next; - } + op = op->next; + while (op != NULL) { + wmOperator *op_next = op->next; + BLI_remlink(&wm->operators, op); + WM_operator_free(op); + op = op_next; + } } /** @@ -121,71 +121,70 @@ void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op) */ void WM_operator_type_set(wmOperator *op, wmOperatorType *ot) { - /* not supported for Python */ - BLI_assert(op->py_instance == NULL); + /* not supported for Python */ + BLI_assert(op->py_instance == NULL); - op->type = ot; - op->ptr->type = ot->srna; + op->type = ot; + op->ptr->type = ot->srna; - /* ensure compatible properties */ - if (op->properties) { - PointerRNA ptr; + /* ensure compatible properties */ + if (op->properties) { + PointerRNA ptr; - WM_operator_properties_create_ptr(&ptr, ot); + WM_operator_properties_create_ptr(&ptr, ot); - WM_operator_properties_default(&ptr, false); + WM_operator_properties_default(&ptr, false); - if (ptr.data) { - IDP_SyncGroupTypes(op->properties, ptr.data, true); - } + if (ptr.data) { + IDP_SyncGroupTypes(op->properties, ptr.data, true); + } - WM_operator_properties_free(&ptr); - } + WM_operator_properties_free(&ptr); + } } static void wm_reports_free(wmWindowManager *wm) { - BKE_reports_clear(&wm->reports); - WM_event_remove_timer(wm, NULL, wm->reports.reporttimer); + BKE_reports_clear(&wm->reports); + WM_event_remove_timer(wm, NULL, wm->reports.reporttimer); } /* all operations get registered in the windowmanager here */ /* called on event handling by event_system.c */ void wm_operator_register(bContext *C, wmOperator *op) { - wmWindowManager *wm = CTX_wm_manager(C); - int tot = 0; - - BLI_addtail(&wm->operators, op); - - /* only count registered operators */ - while (op) { - wmOperator *op_prev = op->prev; - if (op->type->flag & OPTYPE_REGISTER) { - tot += 1; - } - if (tot > MAX_OP_REGISTERED) { - BLI_remlink(&wm->operators, op); - WM_operator_free(op); - } - op = op_prev; - } - - /* so the console is redrawn */ - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); - WM_event_add_notifier(C, NC_WM | ND_HISTORY, NULL); + wmWindowManager *wm = CTX_wm_manager(C); + int tot = 0; + + BLI_addtail(&wm->operators, op); + + /* only count registered operators */ + while (op) { + wmOperator *op_prev = op->prev; + if (op->type->flag & OPTYPE_REGISTER) { + tot += 1; + } + if (tot > MAX_OP_REGISTERED) { + BLI_remlink(&wm->operators, op); + WM_operator_free(op); + } + op = op_prev; + } + + /* so the console is redrawn */ + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); + WM_event_add_notifier(C, NC_WM | ND_HISTORY, NULL); } - void WM_operator_stack_clear(wmWindowManager *wm) { - wmOperator *op; + wmOperator *op; - while ((op = BLI_pophead(&wm->operators))) { - WM_operator_free(op); - } + while ((op = BLI_pophead(&wm->operators))) { + WM_operator_free(op); + } - WM_main_add_notifier(NC_WM | ND_HISTORY, NULL); + WM_main_add_notifier(NC_WM | ND_HISTORY, NULL); } /** @@ -194,238 +193,234 @@ void WM_operator_stack_clear(wmWindowManager *wm) */ void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot) { - wmWindow *win; - for (win = wm->windows.first; win; win = win->next) { - ListBase *lb[2] = {&win->handlers, &win->modalhandlers}; - for (int i = 0; i < ARRAY_SIZE(lb); i++) { - LISTBASE_FOREACH (wmEventHandler *, handler_base, lb[i]) { - if (handler_base->type == WM_HANDLER_TYPE_OP) { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - if (handler->op && handler->op->type == ot) { - /* don't run op->cancel because it needs the context, - * assume whoever unregisters the operator will cleanup */ - handler->head.flag |= WM_HANDLER_DO_FREE; - WM_operator_free(handler->op); - handler->op = NULL; - } - } - } - } - } + wmWindow *win; + for (win = wm->windows.first; win; win = win->next) { + ListBase *lb[2] = {&win->handlers, &win->modalhandlers}; + for (int i = 0; i < ARRAY_SIZE(lb); i++) { + LISTBASE_FOREACH (wmEventHandler *, handler_base, lb[i]) { + if (handler_base->type == WM_HANDLER_TYPE_OP) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + if (handler->op && handler->op->type == ot) { + /* don't run op->cancel because it needs the context, + * assume whoever unregisters the operator will cleanup */ + handler->head.flag |= WM_HANDLER_DO_FREE; + WM_operator_free(handler->op); + handler->op = NULL; + } + } + } + } + } } /* ****************************************** */ void WM_keyconfig_reload(bContext *C) { - if (CTX_py_init_get(C) && !G.background) { + if (CTX_py_init_get(C) && !G.background) { #ifdef WITH_PYTHON - BPY_execute_string( - C, (const char *[]){"bpy", NULL}, - "bpy.utils.keyconfig_init()"); + BPY_execute_string(C, (const char *[]){"bpy", NULL}, "bpy.utils.keyconfig_init()"); #endif - } + } } void WM_keyconfig_init(bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - - /* create standard key configs */ - if (wm->defaultconf == NULL) { - /* Keep lowercase to match the preset filename. */ - wm->defaultconf = WM_keyconfig_new(wm, WM_KEYCONFIG_STR_DEFAULT, false); - } - if (wm->addonconf == NULL) { - wm->addonconf = WM_keyconfig_new(wm, WM_KEYCONFIG_STR_DEFAULT " addon", false); - } - if (wm->userconf == NULL) { - wm->userconf = WM_keyconfig_new(wm, WM_KEYCONFIG_STR_DEFAULT " user", false); - } - - /* initialize only after python init is done, for keymaps that - * use python operators */ - if (CTX_py_init_get(C) && (wm->initialized & WM_KEYCONFIG_IS_INITIALIZED) == 0) { - /* create default key config, only initialize once, - * it's persistent across sessions */ - if (!(wm->defaultconf->flag & KEYCONF_INIT_DEFAULT)) { - wm_window_keymap(wm->defaultconf); - ED_spacetypes_keymap(wm->defaultconf); - - WM_keyconfig_reload(C); - - wm->defaultconf->flag |= KEYCONF_INIT_DEFAULT; - } - - WM_keyconfig_update_tag(NULL, NULL); - WM_keyconfig_update(wm); - - wm->initialized |= WM_KEYCONFIG_IS_INITIALIZED; - } + wmWindowManager *wm = CTX_wm_manager(C); + + /* create standard key configs */ + if (wm->defaultconf == NULL) { + /* Keep lowercase to match the preset filename. */ + wm->defaultconf = WM_keyconfig_new(wm, WM_KEYCONFIG_STR_DEFAULT, false); + } + if (wm->addonconf == NULL) { + wm->addonconf = WM_keyconfig_new(wm, WM_KEYCONFIG_STR_DEFAULT " addon", false); + } + if (wm->userconf == NULL) { + wm->userconf = WM_keyconfig_new(wm, WM_KEYCONFIG_STR_DEFAULT " user", false); + } + + /* initialize only after python init is done, for keymaps that + * use python operators */ + if (CTX_py_init_get(C) && (wm->initialized & WM_KEYCONFIG_IS_INITIALIZED) == 0) { + /* create default key config, only initialize once, + * it's persistent across sessions */ + if (!(wm->defaultconf->flag & KEYCONF_INIT_DEFAULT)) { + wm_window_keymap(wm->defaultconf); + ED_spacetypes_keymap(wm->defaultconf); + + WM_keyconfig_reload(C); + + wm->defaultconf->flag |= KEYCONF_INIT_DEFAULT; + } + + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); + + wm->initialized |= WM_KEYCONFIG_IS_INITIALIZED; + } } void WM_check(bContext *C) { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); - - /* wm context */ - if (wm == NULL) { - wm = CTX_data_main(C)->wm.first; - CTX_wm_manager_set(C, wm); - } - - if (wm == NULL || BLI_listbase_is_empty(&wm->windows)) { - return; - } - - if (!G.background) { - /* case: fileread */ - if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) { - WM_keyconfig_init(C); - WM_autosave_init(wm); - } - - /* case: no open windows at all, for old file reads */ - wm_window_ghostwindows_ensure(wm); - } - - if (wm->message_bus == NULL) { - wm->message_bus = WM_msgbus_create(); - } - - /* case: fileread */ - /* note: this runs in bg mode to set the screen context cb */ - if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) { - ED_screens_initialize(bmain, wm); - wm->initialized |= WM_WINDOW_IS_INITIALIZED; - } + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = CTX_wm_manager(C); + + /* wm context */ + if (wm == NULL) { + wm = CTX_data_main(C)->wm.first; + CTX_wm_manager_set(C, wm); + } + + if (wm == NULL || BLI_listbase_is_empty(&wm->windows)) { + return; + } + + if (!G.background) { + /* case: fileread */ + if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) { + WM_keyconfig_init(C); + WM_autosave_init(wm); + } + + /* case: no open windows at all, for old file reads */ + wm_window_ghostwindows_ensure(wm); + } + + if (wm->message_bus == NULL) { + wm->message_bus = WM_msgbus_create(); + } + + /* case: fileread */ + /* note: this runs in bg mode to set the screen context cb */ + if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) { + ED_screens_initialize(bmain, wm); + wm->initialized |= WM_WINDOW_IS_INITIALIZED; + } } void wm_clear_default_size(bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win; - - /* wm context */ - if (wm == NULL) { - wm = CTX_data_main(C)->wm.first; - CTX_wm_manager_set(C, wm); - } - - if (wm == NULL || BLI_listbase_is_empty(&wm->windows)) { - return; - } - - for (win = wm->windows.first; win; win = win->next) { - win->sizex = 0; - win->sizey = 0; - win->posx = 0; - win->posy = 0; - } - + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win; + + /* wm context */ + if (wm == NULL) { + wm = CTX_data_main(C)->wm.first; + CTX_wm_manager_set(C, wm); + } + + if (wm == NULL || BLI_listbase_is_empty(&wm->windows)) { + return; + } + + for (win = wm->windows.first; win; win = win->next) { + win->sizex = 0; + win->sizey = 0; + win->posx = 0; + win->posy = 0; + } } /* on startup, it adds all data, for matching */ void wm_add_default(Main *bmain, bContext *C) { - wmWindowManager *wm = BKE_libblock_alloc(bmain, ID_WM, "WinMan", 0); - wmWindow *win; - bScreen *screen = CTX_wm_screen(C); /* XXX from file read hrmf */ - WorkSpace *workspace; - WorkSpaceLayout *layout = BKE_workspace_layout_find_global(bmain, screen, &workspace); - - CTX_wm_manager_set(C, wm); - win = wm_window_new(C, NULL); - win->scene = CTX_data_scene(C); - STRNCPY(win->view_layer_name, CTX_data_view_layer(C)->name); - BKE_workspace_active_set(win->workspace_hook, workspace); - BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout); - screen->winid = win->winid; - - wm->winactive = win; - wm->file_saved = 1; - wm_window_make_drawable(wm, win); + wmWindowManager *wm = BKE_libblock_alloc(bmain, ID_WM, "WinMan", 0); + wmWindow *win; + bScreen *screen = CTX_wm_screen(C); /* XXX from file read hrmf */ + WorkSpace *workspace; + WorkSpaceLayout *layout = BKE_workspace_layout_find_global(bmain, screen, &workspace); + + CTX_wm_manager_set(C, wm); + win = wm_window_new(C, NULL); + win->scene = CTX_data_scene(C); + STRNCPY(win->view_layer_name, CTX_data_view_layer(C)->name); + BKE_workspace_active_set(win->workspace_hook, workspace); + BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout); + screen->winid = win->winid; + + wm->winactive = win; + wm->file_saved = 1; + wm_window_make_drawable(wm, win); } - /* context is allowed to be NULL, do not free wm itself (library.c) */ void wm_close_and_free(bContext *C, wmWindowManager *wm) { - wmWindow *win; - wmOperator *op; - wmKeyConfig *keyconf; + wmWindow *win; + wmOperator *op; + wmKeyConfig *keyconf; - if (wm->autosavetimer) { - wm_autosave_timer_ended(wm); - } + if (wm->autosavetimer) { + wm_autosave_timer_ended(wm); + } - while ((win = BLI_pophead(&wm->windows))) { - /* prevent draw clear to use screen */ - BKE_workspace_active_set(win->workspace_hook, NULL); - wm_window_free(C, wm, win); - } + while ((win = BLI_pophead(&wm->windows))) { + /* prevent draw clear to use screen */ + BKE_workspace_active_set(win->workspace_hook, NULL); + wm_window_free(C, wm, win); + } - while ((op = BLI_pophead(&wm->operators))) { - WM_operator_free(op); - } + while ((op = BLI_pophead(&wm->operators))) { + WM_operator_free(op); + } - while ((keyconf = BLI_pophead(&wm->keyconfigs))) { - WM_keyconfig_free(keyconf); - } + while ((keyconf = BLI_pophead(&wm->keyconfigs))) { + WM_keyconfig_free(keyconf); + } - BLI_freelistN(&wm->queue); + BLI_freelistN(&wm->queue); - if (wm->message_bus != NULL) { - WM_msgbus_destroy(wm->message_bus); - } + if (wm->message_bus != NULL) { + WM_msgbus_destroy(wm->message_bus); + } - BLI_freelistN(&wm->paintcursors); + BLI_freelistN(&wm->paintcursors); - WM_drag_free_list(&wm->drags); + WM_drag_free_list(&wm->drags); - wm_reports_free(wm); + wm_reports_free(wm); - if (wm->undo_stack) { - BKE_undosys_stack_destroy(wm->undo_stack); - wm->undo_stack = NULL; - } + if (wm->undo_stack) { + BKE_undosys_stack_destroy(wm->undo_stack); + wm->undo_stack = NULL; + } - if (C && CTX_wm_manager(C) == wm) { - CTX_wm_manager_set(C, NULL); - } + if (C && CTX_wm_manager(C) == wm) { + CTX_wm_manager_set(C, NULL); + } } void wm_close_and_free_all(bContext *C, ListBase *wmlist) { - wmWindowManager *wm; - - while ((wm = wmlist->first)) { - wm_close_and_free(C, wm); - BLI_remlink(wmlist, wm); - BKE_libblock_free_data(&wm->id, true); - MEM_freeN(wm); - } + wmWindowManager *wm; + + while ((wm = wmlist->first)) { + wm_close_and_free(C, wm); + BLI_remlink(wmlist, wm); + BKE_libblock_free_data(&wm->id, true); + MEM_freeN(wm); + } } void WM_main(bContext *C) { - /* Single refresh before handling events. - * This ensures we don't run operators before the depsgraph has been evaluated. */ - wm_event_do_refresh_wm_and_depsgraph(C); + /* Single refresh before handling events. + * This ensures we don't run operators before the depsgraph has been evaluated. */ + wm_event_do_refresh_wm_and_depsgraph(C); - while (1) { + while (1) { - /* get events from ghost, handle window events, add to window queues */ - wm_window_process_events(C); + /* get events from ghost, handle window events, add to window queues */ + wm_window_process_events(C); - /* per window, all events to the window, screen, area and region handlers */ - wm_event_do_handlers(C); + /* per window, all events to the window, screen, area and region handlers */ + wm_event_do_handlers(C); - /* events have left notes about changes, we handle and cache it */ - wm_event_do_notifiers(C); + /* events have left notes about changes, we handle and cache it */ + wm_event_do_notifiers(C); - /* execute cached changes draw */ - wm_draw_update(C); - } + /* execute cached changes draw */ + wm_draw_update(C); + } } diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index a04b3d1c843..45f56968a32 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -47,164 +47,177 @@ /* XXX this still is mess from old code */ - - /* Some simple ghost <-> blender conversions */ static GHOST_TStandardCursor convert_cursor(int curs) { - switch (curs) { - default: - case CURSOR_STD: return GHOST_kStandardCursorDefault; - case CURSOR_FACESEL: return GHOST_kStandardCursorRightArrow; - case CURSOR_WAIT: return GHOST_kStandardCursorWait; - case CURSOR_EDIT: return GHOST_kStandardCursorCrosshair; - case CURSOR_HELP: + switch (curs) { + default: + case CURSOR_STD: + return GHOST_kStandardCursorDefault; + case CURSOR_FACESEL: + return GHOST_kStandardCursorRightArrow; + case CURSOR_WAIT: + return GHOST_kStandardCursorWait; + case CURSOR_EDIT: + return GHOST_kStandardCursorCrosshair; + case CURSOR_HELP: #ifdef __APPLE__ - return GHOST_kStandardCursorLeftRight; + return GHOST_kStandardCursorLeftRight; #else - return GHOST_kStandardCursorHelp; + return GHOST_kStandardCursorHelp; #endif - case CURSOR_X_MOVE: return GHOST_kStandardCursorLeftRight; - case CURSOR_Y_MOVE: return GHOST_kStandardCursorUpDown; - case CURSOR_PENCIL: return GHOST_kStandardCursorPencil; - case CURSOR_COPY: return GHOST_kStandardCursorCopy; - } + case CURSOR_X_MOVE: + return GHOST_kStandardCursorLeftRight; + case CURSOR_Y_MOVE: + return GHOST_kStandardCursorUpDown; + case CURSOR_PENCIL: + return GHOST_kStandardCursorPencil; + case CURSOR_COPY: + return GHOST_kStandardCursorCopy; + } } -static void window_set_custom_cursor(wmWindow *win, unsigned char mask[16][2], - unsigned char bitmap[16][2], int hotx, int hoty) +static void window_set_custom_cursor( + wmWindow *win, unsigned char mask[16][2], unsigned char bitmap[16][2], int hotx, int hoty) { - GHOST_SetCustomCursorShape(win->ghostwin, bitmap, mask, hotx, hoty); + GHOST_SetCustomCursorShape(win->ghostwin, bitmap, mask, hotx, hoty); } static void window_set_custom_cursor_ex(wmWindow *win, BCursor *cursor, int useBig) { - if (useBig) { - GHOST_SetCustomCursorShapeEx(win->ghostwin, - (GHOST_TUns8 *)cursor->big_bm, (GHOST_TUns8 *)cursor->big_mask, - cursor->big_sizex, cursor->big_sizey, - cursor->big_hotx, cursor->big_hoty, - cursor->fg_color, cursor->bg_color); - } - else { - GHOST_SetCustomCursorShapeEx(win->ghostwin, - (GHOST_TUns8 *)cursor->small_bm, (GHOST_TUns8 *)cursor->small_mask, - cursor->small_sizex, cursor->small_sizey, - cursor->small_hotx, cursor->small_hoty, - cursor->fg_color, cursor->bg_color); - } + if (useBig) { + GHOST_SetCustomCursorShapeEx(win->ghostwin, + (GHOST_TUns8 *)cursor->big_bm, + (GHOST_TUns8 *)cursor->big_mask, + cursor->big_sizex, + cursor->big_sizey, + cursor->big_hotx, + cursor->big_hoty, + cursor->fg_color, + cursor->bg_color); + } + else { + GHOST_SetCustomCursorShapeEx(win->ghostwin, + (GHOST_TUns8 *)cursor->small_bm, + (GHOST_TUns8 *)cursor->small_mask, + cursor->small_sizex, + cursor->small_sizey, + cursor->small_hotx, + cursor->small_hoty, + cursor->fg_color, + cursor->bg_color); + } } - /* Cursor Globals */ static BCursor *BlenderCursor[BC_NUMCURSORS]; /*Points to static BCursor Structs */ void WM_cursor_set(wmWindow *win, int curs) { - if (win == NULL || G.background) { - return; /* Can't set custom cursor before Window init */ - } + if (win == NULL || G.background) { + return; /* Can't set custom cursor before Window init */ + } - if (curs == CURSOR_NONE) { - GHOST_SetCursorVisibility(win->ghostwin, 0); - return; - } + if (curs == CURSOR_NONE) { + GHOST_SetCursorVisibility(win->ghostwin, 0); + return; + } #ifdef _WIN32 - /* the default win32 cross cursor is barely visible, - * only 1 pixel thick, use another one instead */ - if (curs == CURSOR_EDIT) { - curs = BC_CROSSCURSOR; - } + /* the default win32 cross cursor is barely visible, + * only 1 pixel thick, use another one instead */ + if (curs == CURSOR_EDIT) { + curs = BC_CROSSCURSOR; + } #else - /* in case of large cursor, also use custom cursor because - * large cursors don't work for system cursors */ - if (U.curssize && curs == CURSOR_EDIT) { - curs = BC_CROSSCURSOR; - } + /* in case of large cursor, also use custom cursor because + * large cursors don't work for system cursors */ + if (U.curssize && curs == CURSOR_EDIT) { + curs = BC_CROSSCURSOR; + } #endif - GHOST_SetCursorVisibility(win->ghostwin, 1); - - if (curs == CURSOR_STD && win->modalcursor) { - curs = win->modalcursor; - } - - win->cursor = curs; - - /* detect if we use system cursor or Blender cursor */ - if (curs >= BC_GHOST_CURSORS) { - GHOST_SetCursorShape(win->ghostwin, convert_cursor(curs)); - } - else { - if ((curs < SYSCURSOR) || (curs >= BC_NUMCURSORS)) { - return; - } - - if (curs == SYSCURSOR) { /* System default Cursor */ - GHOST_SetCursorShape(win->ghostwin, convert_cursor(CURSOR_STD)); - } - else if ((U.curssize == 0) || (BlenderCursor[curs]->big_bm == NULL)) { - window_set_custom_cursor_ex(win, BlenderCursor[curs], 0); - } - else { - window_set_custom_cursor_ex(win, BlenderCursor[curs], 1); - } - } + GHOST_SetCursorVisibility(win->ghostwin, 1); + + if (curs == CURSOR_STD && win->modalcursor) { + curs = win->modalcursor; + } + + win->cursor = curs; + + /* detect if we use system cursor or Blender cursor */ + if (curs >= BC_GHOST_CURSORS) { + GHOST_SetCursorShape(win->ghostwin, convert_cursor(curs)); + } + else { + if ((curs < SYSCURSOR) || (curs >= BC_NUMCURSORS)) { + return; + } + + if (curs == SYSCURSOR) { /* System default Cursor */ + GHOST_SetCursorShape(win->ghostwin, convert_cursor(CURSOR_STD)); + } + else if ((U.curssize == 0) || (BlenderCursor[curs]->big_bm == NULL)) { + window_set_custom_cursor_ex(win, BlenderCursor[curs], 0); + } + else { + window_set_custom_cursor_ex(win, BlenderCursor[curs], 1); + } + } } bool WM_cursor_set_from_tool(struct wmWindow *win, const ScrArea *sa, const ARegion *ar) { - if (ar && (ar->regiontype != RGN_TYPE_WINDOW)) { - return false; - } - - bToolRef_Runtime *tref_rt = (sa && sa->runtime.tool) ? sa->runtime.tool->runtime : NULL; - if (tref_rt && tref_rt->cursor != CURSOR_STD) { - if (win->modalcursor == 0) { - WM_cursor_set(win, tref_rt->cursor); - win->cursor = tref_rt->cursor; - return true; - } - } - return false; + if (ar && (ar->regiontype != RGN_TYPE_WINDOW)) { + return false; + } + + bToolRef_Runtime *tref_rt = (sa && sa->runtime.tool) ? sa->runtime.tool->runtime : NULL; + if (tref_rt && tref_rt->cursor != CURSOR_STD) { + if (win->modalcursor == 0) { + WM_cursor_set(win, tref_rt->cursor); + win->cursor = tref_rt->cursor; + return true; + } + } + return false; } void WM_cursor_modal_set(wmWindow *win, int val) { - if (win->lastcursor == 0) { - win->lastcursor = win->cursor; - } - win->modalcursor = val; - WM_cursor_set(win, val); + if (win->lastcursor == 0) { + win->lastcursor = win->cursor; + } + win->modalcursor = val; + WM_cursor_set(win, val); } void WM_cursor_modal_restore(wmWindow *win) { - win->modalcursor = 0; - if (win->lastcursor) { - WM_cursor_set(win, win->lastcursor); - } - win->lastcursor = 0; + win->modalcursor = 0; + if (win->lastcursor) { + WM_cursor_set(win, win->lastcursor); + } + win->lastcursor = 0; } /* to allow usage all over, we do entire WM */ void WM_cursor_wait(bool val) { - if (!G.background) { - wmWindowManager *wm = G_MAIN->wm.first; - wmWindow *win = wm ? wm->windows.first : NULL; - - for (; win; win = win->next) { - if (val) { - WM_cursor_modal_set(win, BC_WAITCURSOR); - } - else { - WM_cursor_modal_restore(win); - } - } - } + if (!G.background) { + wmWindowManager *wm = G_MAIN->wm.first; + wmWindow *win = wm ? wm->windows.first : NULL; + + for (; win; win = win->next) { + if (val) { + WM_cursor_modal_set(win, BC_WAITCURSOR); + } + else { + WM_cursor_modal_restore(win); + } + } + } } /** @@ -212,127 +225,125 @@ void WM_cursor_wait(bool val) */ void WM_cursor_grab_enable(wmWindow *win, bool wrap, bool hide, int bounds[4]) { - /* Only grab cursor when not running debug. - * It helps not to get a stuck WM when hitting a breakpoint - * */ - GHOST_TGrabCursorMode mode = GHOST_kGrabNormal; - - if (bounds) { - wm_cursor_position_to_ghost(win, &bounds[0], &bounds[1]); - wm_cursor_position_to_ghost(win, &bounds[2], &bounds[3]); - } - - if (hide) { - mode = GHOST_kGrabHide; - } - else if (wrap) { - mode = GHOST_kGrabWrap; - } - if ((G.debug & G_DEBUG) == 0) { - if (win->ghostwin) { - /* Note: There is no tabletdata on Windows if no tablet device is connected. */ - if (win->eventstate->is_motion_absolute == false) { - GHOST_SetCursorGrab(win->ghostwin, mode, bounds, NULL); - } - - win->grabcursor = mode; - } - } + /* Only grab cursor when not running debug. + * It helps not to get a stuck WM when hitting a breakpoint + * */ + GHOST_TGrabCursorMode mode = GHOST_kGrabNormal; + + if (bounds) { + wm_cursor_position_to_ghost(win, &bounds[0], &bounds[1]); + wm_cursor_position_to_ghost(win, &bounds[2], &bounds[3]); + } + + if (hide) { + mode = GHOST_kGrabHide; + } + else if (wrap) { + mode = GHOST_kGrabWrap; + } + if ((G.debug & G_DEBUG) == 0) { + if (win->ghostwin) { + /* Note: There is no tabletdata on Windows if no tablet device is connected. */ + if (win->eventstate->is_motion_absolute == false) { + GHOST_SetCursorGrab(win->ghostwin, mode, bounds, NULL); + } + + win->grabcursor = mode; + } + } } void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2]) { - if ((G.debug & G_DEBUG) == 0) { - if (win && win->ghostwin) { - if (mouse_ungrab_xy) { - int mouse_xy[2] = {mouse_ungrab_xy[0], mouse_ungrab_xy[1]}; - wm_cursor_position_to_ghost(win, &mouse_xy[0], &mouse_xy[1]); - GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, mouse_xy); - } - else { - GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, NULL); - } - - win->grabcursor = GHOST_kGrabDisable; - } - } + if ((G.debug & G_DEBUG) == 0) { + if (win && win->ghostwin) { + if (mouse_ungrab_xy) { + int mouse_xy[2] = {mouse_ungrab_xy[0], mouse_ungrab_xy[1]}; + wm_cursor_position_to_ghost(win, &mouse_xy[0], &mouse_xy[1]); + GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, mouse_xy); + } + else { + GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, NULL); + } + + win->grabcursor = GHOST_kGrabDisable; + } + } } static void wm_cursor_warp_relative(wmWindow *win, int x, int y) { - /* note: don't use wmEvent coords because of continuous grab [#36409] */ - int cx, cy; - wm_get_cursor_position(win, &cx, &cy); - WM_cursor_warp(win, cx + x, cy + y); + /* note: don't use wmEvent coords because of continuous grab [#36409] */ + int cx, cy; + wm_get_cursor_position(win, &cx, &cy); + WM_cursor_warp(win, cx + x, cy + y); } /* give it a modal keymap one day? */ bool wm_cursor_arrow_move(wmWindow *win, const wmEvent *event) { - if (win && event->val == KM_PRESS) { - if (event->type == UPARROWKEY) { - wm_cursor_warp_relative(win, 0, 1); - return 1; - } - else if (event->type == DOWNARROWKEY) { - wm_cursor_warp_relative(win, 0, -1); - return 1; - } - else if (event->type == LEFTARROWKEY) { - wm_cursor_warp_relative(win, -1, 0); - return 1; - } - else if (event->type == RIGHTARROWKEY) { - wm_cursor_warp_relative(win, 1, 0); - return 1; - } - } - return 0; + if (win && event->val == KM_PRESS) { + if (event->type == UPARROWKEY) { + wm_cursor_warp_relative(win, 0, 1); + return 1; + } + else if (event->type == DOWNARROWKEY) { + wm_cursor_warp_relative(win, 0, -1); + return 1; + } + else if (event->type == LEFTARROWKEY) { + wm_cursor_warp_relative(win, -1, 0); + return 1; + } + else if (event->type == RIGHTARROWKEY) { + wm_cursor_warp_relative(win, 1, 0); + return 1; + } + } + return 0; } - /* after this you can call restore too */ void WM_cursor_time(wmWindow *win, int nr) { - /* 10 8x8 digits */ - const char number_bitmaps[10][8] = { - {0, 56, 68, 68, 68, 68, 68, 56}, - {0, 24, 16, 16, 16, 16, 16, 56}, - {0, 60, 66, 32, 16, 8, 4, 126}, - {0, 124, 32, 16, 56, 64, 66, 60}, - {0, 32, 48, 40, 36, 126, 32, 32}, - {0, 124, 4, 60, 64, 64, 68, 56}, - {0, 56, 4, 4, 60, 68, 68, 56}, - {0, 124, 64, 32, 16, 8, 8, 8}, - {0, 60, 66, 66, 60, 66, 66, 60}, - {0, 56, 68, 68, 120, 64, 68, 56}, - }; - unsigned char mask[16][2]; - unsigned char bitmap[16][2] = {{0}}; - int i, idx; - - if (win->lastcursor == 0) { - win->lastcursor = win->cursor; - } - - memset(&mask, 0xFF, sizeof(mask)); - - /* print number bottom right justified */ - for (idx = 3; nr && idx >= 0; idx--) { - const char *digit = number_bitmaps[nr % 10]; - int x = idx % 2; - int y = idx / 2; - - for (i = 0; i < 8; i++) { - bitmap[i + y * 8][x] = digit[i]; - } - nr /= 10; - } - - window_set_custom_cursor(win, mask, bitmap, 7, 7); + /* 10 8x8 digits */ + const char number_bitmaps[10][8] = { + {0, 56, 68, 68, 68, 68, 68, 56}, + {0, 24, 16, 16, 16, 16, 16, 56}, + {0, 60, 66, 32, 16, 8, 4, 126}, + {0, 124, 32, 16, 56, 64, 66, 60}, + {0, 32, 48, 40, 36, 126, 32, 32}, + {0, 124, 4, 60, 64, 64, 68, 56}, + {0, 56, 4, 4, 60, 68, 68, 56}, + {0, 124, 64, 32, 16, 8, 8, 8}, + {0, 60, 66, 66, 60, 66, 66, 60}, + {0, 56, 68, 68, 120, 64, 68, 56}, + }; + unsigned char mask[16][2]; + unsigned char bitmap[16][2] = {{0}}; + int i, idx; + + if (win->lastcursor == 0) { + win->lastcursor = win->cursor; + } + + memset(&mask, 0xFF, sizeof(mask)); + + /* print number bottom right justified */ + for (idx = 3; nr && idx >= 0; idx--) { + const char *digit = number_bitmaps[nr % 10]; + int x = idx % 2; + int y = idx / 2; + + for (i = 0; i < 8; i++) { + bitmap[i + y * 8][x] = digit[i]; + } + nr /= 10; + } + + window_set_custom_cursor(win, mask, bitmap, 7, 7); } - /** * Custom Cursor Description * ========================= @@ -376,1239 +387,1133 @@ void WM_cursor_time(wmWindow *win, int nr) * are for */ #define BEGIN_CURSOR_BLOCK { -#define END_CURSOR_BLOCK } +#define END_CURSOR_BLOCK } void wm_init_cursor_data(void) { - /********************** NW_ARROW Cursor **************************/ -BEGIN_CURSOR_BLOCK - static char nw_sbm[] = { - 0x03, 0x00, 0x05, 0x00, 0x09, 0x00, 0x11, 0x00, - 0x21, 0x00, 0x41, 0x00, 0x81, 0x00, 0x01, 0x01, - 0x01, 0x02, 0xc1, 0x03, 0x49, 0x00, 0x8d, 0x00, - 0x8b, 0x00, 0x10, 0x01, 0x90, 0x01, 0x60, 0x00, - }; - - static char nw_smsk[] = { - 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, - 0x3f, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x01, - 0xff, 0x03, 0xff, 0x03, 0x7f, 0x00, 0xff, 0x00, - 0xfb, 0x00, 0xf0, 0x01, 0xf0, 0x01, 0x60, 0x00, - }; - - static BCursor NWArrowCursor = { - /*small*/ - nw_sbm, nw_smsk, - 16, 16, - 6, 7, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_NW_ARROWCURSOR] = &NWArrowCursor; -END_CURSOR_BLOCK - - ///********************** NS_ARROW Cursor *************************/ -BEGIN_CURSOR_BLOCK - static char ns_sbm[] = { - 0x40, 0x01, 0x20, 0x02, 0x10, 0x04, 0x08, 0x08, - 0x04, 0x10, 0x3c, 0x1e, 0x20, 0x02, 0x20, 0x02, - 0x20, 0x02, 0x20, 0x02, 0x3c, 0x1e, 0x04, 0x10, - 0x08, 0x08, 0x10, 0x04, 0x20, 0x02, 0x40, 0x01, - }; - - static char ns_smsk[] = { - 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, - 0xfc, 0x1f, 0xfc, 0x1f, 0xe0, 0x03, 0xe0, 0x03, - 0xe0, 0x03, 0xe0, 0x03, 0xfc, 0x1f, 0xfc, 0x1f, - 0xf8, 0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, - }; - - static BCursor NSArrowCursor = { - /*small*/ - ns_sbm, ns_smsk, - 16, 16, - 6, 7, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_NS_ARROWCURSOR] = &NSArrowCursor; - -END_CURSOR_BLOCK - /********************** EW_ARROW Cursor *************************/ -BEGIN_CURSOR_BLOCK - static char ew_sbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x38, 0x1c, - 0x2c, 0x34, 0xe6, 0x67, 0x03, 0xc0, 0x01, 0x80, - 0x03, 0xc0, 0xe6, 0x67, 0x2c, 0x34, 0x38, 0x1c, - 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - static char ew_smsk[] = { - 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x38, 0x1c, - 0x3c, 0x3c, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x7f, 0x3c, 0x3c, 0x38, 0x1c, - 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - static BCursor EWArrowCursor = { - /*small*/ - ew_sbm, ew_smsk, - 16, 16, - 7, 6, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_EW_ARROWCURSOR] = &EWArrowCursor; -END_CURSOR_BLOCK - - /********************** Wait Cursor *****************************/ -BEGIN_CURSOR_BLOCK - static char wait_sbm[] = { - 0xfe, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x84, 0x21, - 0xc8, 0x13, 0xd0, 0x0b, 0xa0, 0x04, 0x20, 0x05, - 0xa0, 0x04, 0x10, 0x09, 0x88, 0x11, 0xc4, 0x23, - 0xe2, 0x47, 0xfa, 0x5f, 0x02, 0x40, 0xfe, 0x7f, - }; - - static char wait_smsk[] = { - 0xfe, 0x7f, 0xfe, 0x7f, 0x06, 0x60, 0x8c, 0x31, - 0xd8, 0x1b, 0xf0, 0x0f, 0xe0, 0x06, 0x60, 0x07, - 0xe0, 0x06, 0x30, 0x0d, 0x98, 0x19, 0xcc, 0x33, - 0xe6, 0x67, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, - }; - - static char wait_lbm[] = { - 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, - 0x0c, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x30, - 0x0c, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x18, - 0x18, 0xc0, 0x03, 0x0c, 0x30, 0x20, 0x07, 0x06, - 0x60, 0xf0, 0x0f, 0x03, 0xc0, 0xd0, 0x8d, 0x01, - 0x80, 0x79, 0xcf, 0x00, 0x00, 0xf3, 0x67, 0x00, - 0x00, 0x66, 0x37, 0x00, 0x00, 0x8c, 0x33, 0x00, - 0x00, 0x0c, 0x32, 0x00, 0x00, 0xcc, 0x33, 0x00, - 0x00, 0x8c, 0x30, 0x00, 0x00, 0x46, 0x61, 0x00, - 0x00, 0x03, 0xc3, 0x00, 0x80, 0x01, 0x83, 0x01, - 0xc0, 0xc0, 0x03, 0x03, 0x60, 0xa0, 0x05, 0x06, - 0x30, 0xf0, 0x0f, 0x0c, 0x18, 0xf8, 0x1d, 0x18, - 0x0c, 0x5c, 0x3f, 0x30, 0x0c, 0xff, 0x5f, 0x30, - 0x0c, 0xf7, 0xfe, 0x31, 0xcc, 0xfb, 0x9f, 0x33, - 0x0c, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x30, - 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, - }; - - static char wait_lmsk[] = { - 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, - 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, - 0x3c, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x1e, - 0x78, 0xc0, 0x03, 0x0f, 0xf0, 0xa0, 0x87, 0x07, - 0xe0, 0xf1, 0xcf, 0x03, 0xc0, 0xf3, 0xef, 0x01, - 0x80, 0xff, 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00, - 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, - 0x00, 0x3c, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, - 0x00, 0xbc, 0x3c, 0x00, 0x00, 0xde, 0x79, 0x00, - 0x00, 0x0f, 0xf3, 0x00, 0x80, 0x07, 0xe3, 0x01, - 0xc0, 0xc3, 0xc3, 0x03, 0xe0, 0xe1, 0x87, 0x07, - 0xf0, 0xf0, 0x0f, 0x0f, 0x78, 0xf8, 0x1f, 0x1e, - 0x3c, 0x7c, 0x3f, 0x3c, 0x3c, 0xff, 0x7f, 0x3c, - 0xbc, 0xff, 0xff, 0x3d, 0xfc, 0xfb, 0xbf, 0x3f, - 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, - 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, - }; - - static BCursor WaitCursor = { - /*small*/ - wait_sbm, wait_smsk, - 16, 16, - 7, 7, - /*big*/ - wait_lbm, wait_lmsk, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_WAITCURSOR] = &WaitCursor; -END_CURSOR_BLOCK - - /********************** Cross Cursor ***************************/ -BEGIN_CURSOR_BLOCK - static char cross_sbm[] = { - 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x7e, 0x7e, - 0x7e, 0x7e, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, - }; - - static char cross_smsk[] = { - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0xc0, 0x03, 0x7f, 0xfe, - 0x7f, 0xfe, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - }; - static char cross_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, - 0x00, 0xc0, 0x03, 0x00, 0x00, 0x40, 0x02, 0x00, - 0x00, 0x78, 0x1e, 0x00, 0xfc, 0x1f, 0xf8, 0x3f, - 0xfc, 0x1f, 0xf8, 0x3f, 0x00, 0x78, 0x1e, 0x00, - 0x00, 0x40, 0x02, 0x00, 0x00, 0xc0, 0x03, 0x00, - 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - static char cross_lmsk[] = { - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, - 0x00, 0xe0, 0x07, 0x00, 0x00, 0x70, 0x0e, 0x00, - 0x00, 0x78, 0x1e, 0x00, 0xff, 0x1f, 0xf8, 0xff, - 0xff, 0x1f, 0xf8, 0xff, 0x00, 0x78, 0x1e, 0x00, - 0x00, 0x70, 0x0e, 0x00, 0x00, 0xe0, 0x07, 0x00, - 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - }; - - static BCursor CrossCursor = { - /*small*/ - cross_sbm, cross_smsk, - 16, 16, - 7, 7, - /*big*/ - cross_lbm, cross_lmsk, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_CROSSCURSOR] = &CrossCursor; -END_CURSOR_BLOCK - - /********************** EditCross Cursor ***********************/ -BEGIN_CURSOR_BLOCK - static char editcross_sbm[] = { - 0x0e, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x19, 0x03, - 0x1d, 0x03, 0x11, 0x03, 0x0e, 0x03, 0x00, 0x03, - 0xf8, 0x7c, 0xf8, 0x7c, 0x00, 0x03, 0x00, 0x03, - 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, - }; - - static char editcross_smsk[] = { - 0x0e, 0x00, 0x1f, 0x00, 0x1f, 0x03, 0x1f, 0x03, - 0x1f, 0x03, 0x1f, 0x03, 0x0e, 0x03, 0x80, 0x07, - 0xfc, 0xfc, 0xfc, 0xfc, 0x80, 0x07, 0x00, 0x03, - 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, - }; - - static BCursor EditCrossCursor = { - /*small*/ - editcross_sbm, editcross_smsk, - 16, 16, - 9, 8, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_EDITCROSSCURSOR] = &EditCrossCursor; -END_CURSOR_BLOCK - - /********************** Box Select *************************/ -BEGIN_CURSOR_BLOCK - static char box_sbm[32] = { - 0x7f, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x06, - 0x41, 0x06, 0x41, 0x06, 0x7f, 0x06, 0x00, 0x06, - 0xe0, 0x79, 0xe0, 0x79, 0x00, 0x06, 0x00, 0x06, - 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, - }; - - static char box_smsk[32] = { - 0x7f, 0x00, 0x7f, 0x00, 0x63, 0x06, 0x63, 0x06, - 0x63, 0x06, 0x7f, 0x06, 0x7f, 0x06, 0x00, 0x0f, - 0xf0, 0xf9, 0xf0, 0xf9, 0x00, 0x0f, 0x00, 0x06, - 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, - }; - - static BCursor BoxSelCursor = { - /*small*/ - box_sbm, box_smsk, - 16, 16, - 9, 8, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_BOXSELCURSOR] = &BoxSelCursor; - -END_CURSOR_BLOCK - /********************** Knife Cursor ***********************/ -BEGIN_CURSOR_BLOCK - static char knife_sbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x2c, - 0x00, 0x5a, 0x00, 0x34, 0x00, 0x2a, 0x00, 0x17, - 0x80, 0x06, 0x40, 0x03, 0xa0, 0x03, 0xd0, 0x01, - 0x68, 0x00, 0x1c, 0x00, 0x06, 0x00, 0x00, 0x00, - }; - - static char knife_smsk[] = { - 0x00, 0x60, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0xfe, - 0x00, 0xfe, 0x00, 0x7e, 0x00, 0x7f, 0x80, 0x3f, - 0xc0, 0x0e, 0x60, 0x07, 0xb0, 0x07, 0xd8, 0x03, - 0xec, 0x01, 0x7e, 0x00, 0x1f, 0x00, 0x07, 0x00, - }; - - static char knife_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0xc0, 0x5f, - 0x00, 0x00, 0xc0, 0x6f, 0x00, 0x00, 0xc0, 0x37, - 0x00, 0x00, 0xa8, 0x1b, 0x00, 0x00, 0x54, 0x0d, - 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x54, 0x00, - 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x53, 0x00, - 0x00, 0xc0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, - 0x00, 0xd0, 0x0f, 0x00, 0x00, 0xe8, 0x07, 0x00, - 0x00, 0xf4, 0x07, 0x00, 0x00, 0xfa, 0x00, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x80, 0x0e, 0x00, 0x00, - 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - static char knife_lmsk[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x7e, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x80, 0xff, - 0x00, 0x00, 0xc0, 0xbf, 0x00, 0x00, 0xe0, 0xdf, - 0x00, 0x00, 0xe0, 0xef, 0x00, 0x00, 0xf8, 0x77, - 0x00, 0x00, 0xfc, 0x3b, 0x00, 0x00, 0xfe, 0x1d, - 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xfe, 0x01, - 0x00, 0x00, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x00, - 0x00, 0xe0, 0x7f, 0x00, 0x00, 0xf0, 0x1f, 0x00, - 0x00, 0xd8, 0x1f, 0x00, 0x00, 0xec, 0x0f, 0x00, - 0x00, 0xf6, 0x0f, 0x00, 0x00, 0xfb, 0x06, 0x00, - 0x80, 0xbd, 0x01, 0x00, 0xc0, 0x6e, 0x00, 0x00, - 0xe0, 0x1b, 0x00, 0x00, 0xf0, 0x06, 0x00, 0x00, - 0xb8, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - static BCursor KnifeCursor = { - /*small*/ - knife_sbm, knife_smsk, - 16, 16, - 0, 15, - /*big*/ - knife_lbm, knife_lmsk, - 32, 32, - 0, 31, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_KNIFECURSOR] = &KnifeCursor; - -END_CURSOR_BLOCK - - /********************** Loop Select Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char vloop_sbm[] = { - 0x00, 0x00, 0x7e, 0x00, 0x3e, 0x00, 0x1e, 0x00, - 0x0e, 0x00, 0x66, 0x60, 0x62, 0x6f, 0x00, 0x00, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x00, 0x00, 0x60, 0x60, 0x60, 0x6f, 0x00, 0x00, - }; - - static char vloop_smsk[] = { - 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00, - 0xff, 0xf0, 0xff, 0xff, 0xf7, 0xff, 0xf3, 0xf0, - 0x61, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, - 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xff, 0xf0, 0xf0, - }; - - - - static char vloop_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, - 0xfc, 0x0f, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, - 0xfc, 0x03, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, - 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, - 0x3c, 0x3c, 0x00, 0x3c, 0x3c, 0x3c, 0x00, 0x3c, - 0x0c, 0x3c, 0xff, 0x3c, 0x0c, 0x3c, 0xff, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, - 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, - 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, - 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, - 0x00, 0x3c, 0xff, 0x3c, 0x00, 0x3c, 0xff, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - static char vloop_lmsk[] = { - 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0x03, 0x00, - 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, - 0xff, 0x3f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, - 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, - 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, - 0x0f, 0xff, 0x00, 0xff, 0x0f, 0xff, 0x00, 0xff, - 0x03, 0x3c, 0x00, 0x3c, 0x03, 0x3c, 0x00, 0x3c, - 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, - 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, - 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, - 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - }; - - - - static BCursor VLoopCursor = { - /*small*/ - vloop_sbm, vloop_smsk, - 16, 16, - 0, 0, - /*big*/ - vloop_lbm, vloop_lmsk, - 32, 32, - 0, 0, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_VLOOPCURSOR] = &VLoopCursor; - -END_CURSOR_BLOCK - - - /********************** TextEdit Cursor ***********************/ -BEGIN_CURSOR_BLOCK - static char textedit_sbm[] = { - 0xe0, 0x03, 0x10, 0x04, 0x60, 0x03, 0x40, 0x01, - 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, - 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, - 0x40, 0x01, 0x60, 0x03, 0x10, 0x04, 0xe0, 0x03, - }; - - static char textedit_smsk[] = { - 0xe0, 0x03, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, - 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, - 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, - 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xe0, 0x03, - }; - - static BCursor TextEditCursor = { - /*small*/ - textedit_sbm, textedit_smsk, - 16, 16, - 9, 8, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_TEXTEDITCURSOR] = &TextEditCursor; -END_CURSOR_BLOCK - - - /********************** Paintbrush Cursor ***********************/ -BEGIN_CURSOR_BLOCK - static char paintbrush_sbm[] = { - - 0x00, 0xe0, 0x00, 0x98, 0x00, 0x44, 0x00, 0x42, - 0x00, 0x21, 0x80, 0x20, 0x40, 0x13, 0x40, 0x17, - 0xa0, 0x0b, 0x98, 0x05, 0x04, 0x02, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x81, 0x00, 0x7f, 0x00, - }; - - static char paintbrush_smsk[] = { - 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x7c, 0x00, 0x7e, - 0x00, 0x3f, 0x80, 0x3f, 0xc0, 0x1f, 0xc0, 0x1f, - 0xe0, 0x0f, 0xf8, 0x07, 0xfc, 0x03, 0xfe, 0x01, - 0xfe, 0x01, 0xfe, 0x01, 0xff, 0x00, 0x7f, 0x00, - }; - - static BCursor PaintBrushCursor = { - /*small*/ - paintbrush_sbm, paintbrush_smsk, - 16, 16, - 0, 15, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_PAINTBRUSHCURSOR] = &PaintBrushCursor; -END_CURSOR_BLOCK - - -/********************** Hand Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char hand_sbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x0d, - 0x98, 0x6d, 0x98, 0x6d, 0xb0, 0x6d, 0xb0, 0x6d, - 0xe0, 0x6f, 0xe6, 0x7f, 0xee, 0x7f, 0xfc, 0x3f, - 0xf8, 0x3f, 0xf0, 0x1f, 0xc0, 0x1f, 0xc0, 0x1f, - }; - - static char hand_smsk[] = { - 0x00, 0x00, 0x80, 0x01, 0xc0, 0x0f, 0xd8, 0x7f, - 0xfc, 0xff, 0xfc, 0xff, 0xf8, 0xff, 0xf8, 0xff, - 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, - 0xfc, 0x7f, 0xf8, 0x3f, 0xf0, 0x3f, 0xe0, 0x3f, - }; - - - static BCursor HandCursor = { - /*small*/ - hand_sbm, hand_smsk, - 16, 16, - 8, 8, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_HANDCURSOR] = &HandCursor; - -END_CURSOR_BLOCK - -/********************** NSEW Scroll Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char nsewscroll_sbm[] = { - 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xc0, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0e, 0x70, - 0x0e, 0x70, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00, - }; - - static char nsewscroll_smsk[] = { - 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xe0, 0x07, - 0xc0, 0x03, 0x0c, 0x30, 0x1e, 0x78, 0x1f, 0xf8, - 0x1f, 0xf8, 0x1e, 0x78, 0x0c, 0x30, 0xc0, 0x03, - 0xe0, 0x07, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, - }; - - - static BCursor NSEWScrollCursor = { - /*small*/ - nsewscroll_sbm, nsewscroll_smsk, - 16, 16, - 8, 8, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_NSEW_SCROLLCURSOR] = &NSEWScrollCursor; - -END_CURSOR_BLOCK - - -/********************** NS Scroll Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char nsscroll_sbm[] = { - 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xc0, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00, - }; - - static char nsscroll_smsk[] = { - 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xe0, 0x07, - 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, - 0xe0, 0x07, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, - }; - - - static BCursor NSScrollCursor = { - /*small*/ - nsscroll_sbm, nsscroll_smsk, - 16, 16, - 8, 8, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_NS_SCROLLCURSOR] = &NSScrollCursor; - -END_CURSOR_BLOCK - - -/********************** EW Scroll Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char ewscroll_sbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0e, 0x70, - 0x0e, 0x70, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - static char ewscroll_smsk[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x30, 0x1e, 0x78, 0x1f, 0xf8, - 0x1f, 0xf8, 0x1e, 0x78, 0x0c, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - - static BCursor EWScrollCursor = { - /*small*/ - ewscroll_sbm, ewscroll_smsk, - 16, 16, - 8, 8, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_EW_SCROLLCURSOR] = &EWScrollCursor; - -END_CURSOR_BLOCK - -/********************** Eyedropper Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char eyedropper_sbm[] = { - 0x00, 0x30, 0x00, 0x48, 0x00, 0x85, 0x80, 0x82, - 0x40, 0x40, 0x80, 0x20, 0x40, 0x11, 0xa0, 0x23, - 0xd0, 0x15, 0xe8, 0x0a, 0x74, 0x01, 0xb4, 0x00, - 0x4a, 0x00, 0x35, 0x00, 0x08, 0x00, 0x04, 0x00, - }; - - static char eyedropper_smsk[] = { - 0x00, 0x30, 0x00, 0x78, 0x00, 0xfd, 0x80, 0xff, - 0xc0, 0x7f, 0x80, 0x3f, 0xc0, 0x1f, 0xe0, 0x3f, - 0xf0, 0x1f, 0xf8, 0x0b, 0xfc, 0x01, 0xfc, 0x00, - 0x7e, 0x00, 0x3f, 0x00, 0x0c, 0x00, 0x04, 0x00, - }; - - - static BCursor EyedropperCursor = { - /*small*/ - eyedropper_sbm, eyedropper_smsk, - 16, 16, - 1, 15, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE, - }; - - BlenderCursor[BC_EYEDROPPER_CURSOR] = &EyedropperCursor; - -END_CURSOR_BLOCK - -/********************** Swap Area Cursor ***********************/ -BEGIN_CURSOR_BLOCK - static char swap_sbm[] = { - 0xc0, 0xff, 0x40, 0x80, 0x40, 0x80, 0x40, 0x9c, - 0x40, 0x98, 0x40, 0x94, 0x00, 0x82, 0xfe, 0x80, - 0x7e, 0xfd, 0xbe, 0x01, 0xda, 0x01, 0xe2, 0x01, - 0xe2, 0x01, 0xc2, 0x01, 0xfe, 0x01, 0x00, 0x00, - }; - - static char swap_smsk[] = { - 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, - 0xc0, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, - 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, - }; - - static BCursor SwapCursor = { - /*small*/ - swap_sbm, swap_smsk, - 16, 16, - 8, 8, - /*big*/ - NULL, NULL, - 32, 32, - 15, 15, - /*color*/ - BC_YELLOW, BC_BLUE, - }; - - BlenderCursor[BC_SWAPAREA_CURSOR] = &SwapCursor; - -END_CURSOR_BLOCK - -/********************** Horizontal Split Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char hsplit_sbm[] = { - 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x88, 0x08, 0x8C, 0x18, 0x8E, 0x38, - 0x8C, 0x18, 0x88, 0x08, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char hsplit_smsk[] = { - 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xD0, 0x05, - 0xD8, 0x0D, 0xDC, 0x1D, 0xDE, 0x3D, 0xDF, 0x7D, - 0xDE, 0x3D, 0xDC, 0x1D, 0xD8, 0x0D, 0xD0, 0x05, - 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00 - }; - - static char hsplit_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x84, 0x21, 0x00, 0x00, 0x86, 0x61, 0x00, - 0x00, 0x87, 0xE1, 0x00, 0x80, 0x87, 0xE1, 0x01, - 0xC0, 0x87, 0xE1, 0x03, 0xE0, 0x87, 0xE1, 0x07, - 0xF0, 0x87, 0xE1, 0x0F, 0xF8, 0x87, 0xE1, 0x1F, - 0xF0, 0x87, 0xE1, 0x0F, 0xE0, 0x87, 0xE1, 0x07, - 0xC0, 0x87, 0xE1, 0x03, 0x80, 0x87, 0xE1, 0x01, - 0x00, 0x87, 0xE1, 0x00, 0x00, 0x86, 0x61, 0x00, - 0x00, 0x84, 0x21, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char hsplit_lmsk[] = { - 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, - 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, - 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC8, 0x13, 0x00, - 0x00, 0xCC, 0x33, 0x00, 0x00, 0xCE, 0x73, 0x00, - 0x00, 0xCF, 0xF3, 0x00, 0x80, 0xCF, 0xF3, 0x01, - 0xC0, 0xCF, 0xF3, 0x03, 0xE0, 0xCF, 0xF3, 0x07, - 0xF0, 0xCF, 0xF3, 0x0F, 0xF8, 0xCF, 0xF3, 0x1F, - 0xFC, 0xCF, 0xF3, 0x3F, 0xFE, 0xCF, 0xF3, 0x7F, - 0xFC, 0xCF, 0xF3, 0x3F, 0xF8, 0xCF, 0xF3, 0x1F, - 0xF0, 0xCF, 0xF3, 0x0F, 0xE0, 0xCF, 0xF3, 0x07, - 0xC0, 0xCF, 0xF3, 0x03, 0x80, 0xCF, 0xF3, 0x01, - 0x00, 0xCF, 0xF3, 0x00, 0x00, 0xCE, 0x73, 0x00, - 0x00, 0xCC, 0x33, 0x00, 0x00, 0xC8, 0x13, 0x00, - 0x00, 0xC8, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, - 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, - 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static BCursor HSplitCursor = { - /*small*/ - hsplit_sbm, hsplit_smsk, - 16, 16, - 7, 7, - /*big*/ - hsplit_lbm, hsplit_lmsk, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE - }; - - BlenderCursor[BC_H_SPLITCURSOR] = &HSplitCursor; - -END_CURSOR_BLOCK - -/********************** Vertical Split Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char vsplit_sbm[] = { - 0x00, 0x00, 0x80, 0x00, 0xC0, 0x01, 0xE0, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, - 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char vsplit_smsk[] = { - 0x80, 0x00, 0xC0, 0x01, 0xE0, 0x03, 0xF0, 0x07, - 0xF8, 0x0F, 0x00, 0x00, 0xFF, 0x7F, 0xFF, 0x7F, - 0xFF, 0x7F, 0x00, 0x00, 0xF8, 0x0F, 0xF0, 0x07, - 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00 - }; - - static char vsplit_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0xC0, 0x01, 0x00, 0x00, 0xE0, 0x03, 0x00, - 0x00, 0xF0, 0x07, 0x00, 0x00, 0xF8, 0x0F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x3F, - 0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF0, 0x07, 0x00, - 0x00, 0xE0, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char vsplit_lmsk[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0xC0, 0x01, 0x00, 0x00, 0xE0, 0x03, 0x00, - 0x00, 0xF0, 0x07, 0x00, 0x00, 0xF8, 0x0F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0x00, - 0xC0, 0xFF, 0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0x01, - 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x7F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF0, 0x07, 0x00, - 0x00, 0xE0, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static BCursor VSplitCursor = { - /*small*/ - vsplit_sbm, vsplit_smsk, - 16, 16, - 7, 7, - /*big*/ - vsplit_lbm, vsplit_lmsk, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE - }; - - BlenderCursor[BC_V_SPLITCURSOR] = &VSplitCursor; - -END_CURSOR_BLOCK - -/********************** North Arrow Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char narrow_sbm[] = { - 0x00, 0x00, 0x80, 0x00, 0xC0, 0x01, 0xE0, 0x03, - 0xF0, 0x07, 0xF8, 0x0F, 0xFC, 0x1F, 0xE0, 0x03, - 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char narrow_smsk[] = { - 0x80, 0x00, 0xC0, 0x01, 0xE0, 0x03, 0xF0, 0x07, - 0xF8, 0x0F, 0xFC, 0x1F, 0xFE, 0x3F, 0xFF, 0x7F, - 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char narrow_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, - 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF0, 0x07, 0x00, - 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFF, 0x7F, 0x00, - 0x80, 0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0x01, - 0xE0, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0x07, - 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char narrow_lmsk[] = { - 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, - 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF0, 0x07, 0x00, - 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFF, 0x7F, 0x00, - 0x80, 0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0x01, - 0xE0, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0x07, - 0xF8, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x1F, - 0xFE, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static BCursor NArrowCursor = { - /*small*/ - narrow_sbm, narrow_smsk, - 16, 16, - 7, 4, - /*big*/ - narrow_lbm, narrow_lmsk, - 32, 32, - 15, 10, - /*color*/ - BC_BLACK, BC_WHITE - }; - - BlenderCursor[BC_N_ARROWCURSOR] = &NArrowCursor; - -END_CURSOR_BLOCK - -/********************** South Arrow Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char sarrow_sbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, - 0xE0, 0x03, 0xFC, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, - 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00 - }; - - static char sarrow_smsk[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, - 0xFF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, 0x0F, - 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00 - }; - - static char sarrow_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0xFF, 0xFF, 0x0F, - 0xF0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0x03, - 0xC0, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0x00, - 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF8, 0x0F, 0x00, - 0x00, 0xF0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0x00, - 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char sarrow_lmsk[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0x3F, - 0xFC, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0x0F, - 0xF0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0x03, - 0xC0, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0x00, - 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0x3F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF8, 0x0F, 0x00, - 0x00, 0xF0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0x00, - 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00 - }; - - static BCursor SArrowCursor = { - /*small*/ - sarrow_sbm, sarrow_smsk, - 16, 16, - 7, 11, - /*big*/ - sarrow_lbm, sarrow_lmsk, - 32, 32, - 15, 21, - /*color*/ - BC_BLACK, BC_WHITE - }; - - BlenderCursor[BC_S_ARROWCURSOR] = &SArrowCursor; - -END_CURSOR_BLOCK - -/********************** East Arrow Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char earrow_sbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, - 0x00, 0x0E, 0xE0, 0x1F, 0xE0, 0x3F, 0xE0, 0x7F, - 0xE0, 0x3F, 0xE0, 0x1F, 0x00, 0x0E, 0x00, 0x06, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char earrow_smsk[] = { - 0x00, 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0F, - 0xF0, 0x1F, 0xF0, 0x3F, 0xF0, 0x7F, 0xF0, 0xFF, - 0xF0, 0x7F, 0xF0, 0x3F, 0xF0, 0x1F, 0x00, 0x0F, - 0x00, 0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00 - }; - - static char earrow_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3E, 0x00, - 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFE, 0x00, - 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0x03, - 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x0F, - 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0xFF, 0xFF, 0x3F, - 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0xFF, 0xFF, 0x0F, - 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x03, - 0x00, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xFE, 0x00, - 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x3E, 0x00, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char earrow_lmsk[] = { - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x00, - 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0x00, - 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0x00, - 0x00, 0x00, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0x03, - 0x80, 0xFF, 0xFF, 0x07, 0x80, 0xFF, 0xFF, 0x0F, - 0x80, 0xFF, 0xFF, 0x1F, 0x80, 0xFF, 0xFF, 0x3F, - 0x80, 0xFF, 0xFF, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, - 0x80, 0xFF, 0xFF, 0x7F, 0x80, 0xFF, 0xFF, 0x3F, - 0x80, 0xFF, 0xFF, 0x1F, 0x80, 0xFF, 0xFF, 0x0F, - 0x80, 0xFF, 0xFF, 0x07, 0x80, 0xFF, 0xFF, 0x03, - 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0xFF, 0x00, - 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3F, 0x00, - 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static BCursor EArrowCursor = { - /*small*/ - earrow_sbm, earrow_smsk, - 16, 16, - 11, 7, - /*big*/ - earrow_lbm, earrow_lmsk, - 32, 32, - 15, 22, - /*color*/ - BC_BLACK, BC_WHITE - }; - - BlenderCursor[BC_E_ARROWCURSOR] = &EArrowCursor; - -END_CURSOR_BLOCK - -/********************** West Arrow Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char warrow_sbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, - 0x70, 0x00, 0xF8, 0x07, 0xFC, 0x07, 0xFE, 0x07, - 0xFC, 0x07, 0xF8, 0x07, 0x70, 0x00, 0x60, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char warrow_smsk[] = { - 0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0xF0, 0x00, - 0xF8, 0x0F, 0xFC, 0x0F, 0xFE, 0x0F, 0xFF, 0x0F, - 0xFE, 0x0F, 0xFC, 0x0F, 0xF8, 0x0F, 0xF0, 0x00, - 0xE0, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x00 - }; - - static char warrow_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x80, 0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0x00, - 0xE0, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x00, - 0xF8, 0xFF, 0xFF, 0x00, 0xFC, 0xFF, 0xFF, 0x00, - 0xF8, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x00, - 0xE0, 0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0x00, - 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char warrow_lmsk[] = { - 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, - 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, - 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x80, 0xFF, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x01, - 0xE0, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0xFF, 0x01, - 0xF8, 0xFF, 0xFF, 0x01, 0xFC, 0xFF, 0xFF, 0x01, - 0xFE, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x01, - 0xFE, 0xFF, 0xFF, 0x01, 0xFC, 0xFF, 0xFF, 0x01, - 0xF8, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0xFF, 0x01, - 0xE0, 0xFF, 0xFF, 0x01, 0xC0, 0xFF, 0xFF, 0x01, - 0x80, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static BCursor WArrowCursor = { - /*small*/ - warrow_sbm, warrow_smsk, - 16, 16, - 4, 7, - /*big*/ - warrow_lbm, warrow_lmsk, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE - }; - - BlenderCursor[BC_W_ARROWCURSOR] = &WArrowCursor; - -END_CURSOR_BLOCK - - -/********************** Stop Sign Cursor ***********************/ -BEGIN_CURSOR_BLOCK - - static char stop_sbm[] = { - 0x00, 0x00, 0xE0, 0x07, 0x38, 0x1C, 0x1C, 0x30, - 0x3C, 0x20, 0x76, 0x60, 0xE2, 0x40, 0xC2, 0x41, - 0x82, 0x43, 0x02, 0x47, 0x06, 0x6E, 0x04, 0x3C, - 0x0C, 0x38, 0x38, 0x1C, 0xE0, 0x07, 0x00, 0x00 - }; - - static char stop_smsk[] = { - 0xE0, 0x07, 0xF8, 0x1F, 0xFC, 0x3F, 0x3E, 0x7C, - 0x7E, 0x70, 0xFF, 0xF0, 0xF7, 0xE1, 0xE7, 0xE3, - 0xC7, 0xE7, 0x87, 0xEF, 0x0F, 0xFF, 0x0E, 0x7E, - 0x3E, 0x7C, 0xFC, 0x3F, 0xF8, 0x1F, 0xE0, 0x07 - }; - - static char stop_lbm[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x00, - 0x00, 0xFE, 0x7F, 0x00, 0x00, 0x0F, 0xF0, 0x00, - 0xC0, 0x03, 0xC0, 0x03, 0xE0, 0x01, 0x00, 0x07, - 0xF0, 0x01, 0x00, 0x0E, 0xF0, 0x01, 0x00, 0x0C, - 0xF8, 0x03, 0x00, 0x18, 0x1C, 0x07, 0x00, 0x38, - 0x0C, 0x0E, 0x00, 0x30, 0x0C, 0x1C, 0x00, 0x30, - 0x06, 0x38, 0x00, 0x60, 0x06, 0x70, 0x00, 0x60, - 0x06, 0xE0, 0x00, 0x60, 0x06, 0xC0, 0x01, 0x60, - 0x06, 0x80, 0x03, 0x60, 0x06, 0x00, 0x07, 0x60, - 0x06, 0x00, 0x0E, 0x60, 0x06, 0x00, 0x1C, 0x60, - 0x0C, 0x00, 0x38, 0x30, 0x0C, 0x00, 0x70, 0x30, - 0x1C, 0x00, 0xE0, 0x38, 0x18, 0x00, 0xC0, 0x1F, - 0x30, 0x00, 0x80, 0x0F, 0x70, 0x00, 0x80, 0x0F, - 0xE0, 0x00, 0x80, 0x07, 0xC0, 0x03, 0xC0, 0x03, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFE, 0x7F, 0x00, - 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static char stop_lmsk[] = { - 0x00, 0xF0, 0x0F, 0x00, 0x00, 0xFE, 0x7F, 0x00, - 0x80, 0xFF, 0xFF, 0x01, 0xC0, 0xFF, 0xFF, 0x03, - 0xE0, 0x1F, 0xF8, 0x07, 0xF0, 0x03, 0xC0, 0x0F, - 0xF8, 0x03, 0x80, 0x1F, 0xFC, 0x07, 0x00, 0x3F, - 0xFC, 0x0F, 0x00, 0x3E, 0xFE, 0x1F, 0x00, 0x7C, - 0x9E, 0x3F, 0x00, 0x78, 0x1E, 0x7F, 0x00, 0x78, - 0x1F, 0xFE, 0x00, 0xF8, 0x0F, 0xFC, 0x01, 0xF0, - 0x0F, 0xF8, 0x03, 0xF0, 0x0F, 0xF0, 0x07, 0xF0, - 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xC0, 0x1F, 0xF0, - 0x0F, 0x80, 0x3F, 0xF0, 0x1F, 0x00, 0x7F, 0xF8, - 0x1E, 0x00, 0xFE, 0x78, 0x1E, 0x00, 0xFC, 0x79, - 0x3E, 0x00, 0xF8, 0x7F, 0x7C, 0x00, 0xF0, 0x3F, - 0xFC, 0x00, 0xE0, 0x3F, 0xF8, 0x01, 0xC0, 0x1F, - 0xF0, 0x03, 0xC0, 0x0F, 0xE0, 0x1F, 0xF8, 0x07, - 0xC0, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0x01, - 0x00, 0xFE, 0x7F, 0x00, 0x00, 0xF0, 0x0F, 0x00 - }; - - static BCursor StopCursor = { - /*small*/ - stop_sbm, stop_smsk, - 16, 16, - 7, 7, - /*big*/ - stop_lbm, stop_lmsk, - 32, 32, - 15, 15, - /*color*/ - BC_BLACK, BC_WHITE - }; - - BlenderCursor[BC_STOPCURSOR] = &StopCursor; - -END_CURSOR_BLOCK - -/********************** Put the cursors in the array ***********************/ - + /********************** NW_ARROW Cursor **************************/ + BEGIN_CURSOR_BLOCK + static char nw_sbm[] = { + 0x03, 0x00, 0x05, 0x00, 0x09, 0x00, 0x11, 0x00, 0x21, 0x00, 0x41, + 0x00, 0x81, 0x00, 0x01, 0x01, 0x01, 0x02, 0xc1, 0x03, 0x49, 0x00, + 0x8d, 0x00, 0x8b, 0x00, 0x10, 0x01, 0x90, 0x01, 0x60, 0x00, + }; + + static char nw_smsk[] = { + 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00, 0x7f, + 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x03, 0x7f, 0x00, + 0xff, 0x00, 0xfb, 0x00, 0xf0, 0x01, 0xf0, 0x01, 0x60, 0x00, + }; + + static BCursor NWArrowCursor = { + /*small*/ + nw_sbm, + nw_smsk, + 16, + 16, + 6, + 7, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_NW_ARROWCURSOR] = &NWArrowCursor; + END_CURSOR_BLOCK + + ///********************** NS_ARROW Cursor *************************/ + BEGIN_CURSOR_BLOCK + static char ns_sbm[] = { + 0x40, 0x01, 0x20, 0x02, 0x10, 0x04, 0x08, 0x08, 0x04, 0x10, 0x3c, + 0x1e, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x3c, 0x1e, + 0x04, 0x10, 0x08, 0x08, 0x10, 0x04, 0x20, 0x02, 0x40, 0x01, + }; + + static char ns_smsk[] = { + 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 0xfc, 0x1f, 0xfc, + 0x1f, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xfc, 0x1f, + 0xfc, 0x1f, 0xf8, 0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, + }; + + static BCursor NSArrowCursor = { + /*small*/ + ns_sbm, + ns_smsk, + 16, + 16, + 6, + 7, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_NS_ARROWCURSOR] = &NSArrowCursor; + + END_CURSOR_BLOCK + /********************** EW_ARROW Cursor *************************/ + BEGIN_CURSOR_BLOCK + static char ew_sbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x38, 0x1c, 0x2c, 0x34, 0xe6, + 0x67, 0x03, 0xc0, 0x01, 0x80, 0x03, 0xc0, 0xe6, 0x67, 0x2c, 0x34, + 0x38, 0x1c, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static char ew_smsk[] = { + 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x38, 0x1c, 0x3c, 0x3c, 0xfe, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x3c, 0x3c, + 0x38, 0x1c, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static BCursor EWArrowCursor = { + /*small*/ + ew_sbm, + ew_smsk, + 16, + 16, + 7, + 6, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_EW_ARROWCURSOR] = &EWArrowCursor; + END_CURSOR_BLOCK + + /********************** Wait Cursor *****************************/ + BEGIN_CURSOR_BLOCK + static char wait_sbm[] = { + 0xfe, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x84, 0x21, 0xc8, 0x13, 0xd0, + 0x0b, 0xa0, 0x04, 0x20, 0x05, 0xa0, 0x04, 0x10, 0x09, 0x88, 0x11, + 0xc4, 0x23, 0xe2, 0x47, 0xfa, 0x5f, 0x02, 0x40, 0xfe, 0x7f, + }; + + static char wait_smsk[] = { + 0xfe, 0x7f, 0xfe, 0x7f, 0x06, 0x60, 0x8c, 0x31, 0xd8, 0x1b, 0xf0, + 0x0f, 0xe0, 0x06, 0x60, 0x07, 0xe0, 0x06, 0x30, 0x0d, 0x98, 0x19, + 0xcc, 0x33, 0xe6, 0x67, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, + }; + + static char wait_lbm[] = { + 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0x0c, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, + 0x30, 0x0c, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x18, 0x18, 0xc0, 0x03, 0x0c, 0x30, 0x20, + 0x07, 0x06, 0x60, 0xf0, 0x0f, 0x03, 0xc0, 0xd0, 0x8d, 0x01, 0x80, 0x79, 0xcf, 0x00, 0x00, + 0xf3, 0x67, 0x00, 0x00, 0x66, 0x37, 0x00, 0x00, 0x8c, 0x33, 0x00, 0x00, 0x0c, 0x32, 0x00, + 0x00, 0xcc, 0x33, 0x00, 0x00, 0x8c, 0x30, 0x00, 0x00, 0x46, 0x61, 0x00, 0x00, 0x03, 0xc3, + 0x00, 0x80, 0x01, 0x83, 0x01, 0xc0, 0xc0, 0x03, 0x03, 0x60, 0xa0, 0x05, 0x06, 0x30, 0xf0, + 0x0f, 0x0c, 0x18, 0xf8, 0x1d, 0x18, 0x0c, 0x5c, 0x3f, 0x30, 0x0c, 0xff, 0x5f, 0x30, 0x0c, + 0xf7, 0xfe, 0x31, 0xcc, 0xfb, 0x9f, 0x33, 0x0c, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x30, + 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, + }; + + static char wait_lmsk[] = { + 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, + 0x3f, 0x3c, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x1e, 0x78, 0xc0, 0x03, 0x0f, 0xf0, 0xa0, + 0x87, 0x07, 0xe0, 0xf1, 0xcf, 0x03, 0xc0, 0xf3, 0xef, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00, + 0xff, 0x7f, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x3c, 0x3f, 0x00, + 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xbc, 0x3c, 0x00, 0x00, 0xde, 0x79, 0x00, 0x00, 0x0f, 0xf3, + 0x00, 0x80, 0x07, 0xe3, 0x01, 0xc0, 0xc3, 0xc3, 0x03, 0xe0, 0xe1, 0x87, 0x07, 0xf0, 0xf0, + 0x0f, 0x0f, 0x78, 0xf8, 0x1f, 0x1e, 0x3c, 0x7c, 0x3f, 0x3c, 0x3c, 0xff, 0x7f, 0x3c, 0xbc, + 0xff, 0xff, 0x3d, 0xfc, 0xfb, 0xbf, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, + 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, + }; + + static BCursor WaitCursor = { + /*small*/ + wait_sbm, + wait_smsk, + 16, + 16, + 7, + 7, + /*big*/ + wait_lbm, + wait_lmsk, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_WAITCURSOR] = &WaitCursor; + END_CURSOR_BLOCK + + /********************** Cross Cursor ***************************/ + BEGIN_CURSOR_BLOCK + static char cross_sbm[] = { + 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, 0x01, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, + }; + + static char cross_smsk[] = { + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0xc0, 0x03, 0x7f, 0xfe, 0x7f, 0xfe, 0xc0, 0x03, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + }; + static char cross_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x78, 0x1e, 0x00, + 0xfc, 0x1f, 0xf8, 0x3f, 0xfc, 0x1f, 0xf8, 0x3f, 0x00, 0x78, 0x1e, 0x00, 0x00, 0x40, 0x02, + 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static char cross_lmsk[] = { + 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x70, 0x0e, 0x00, 0x00, 0x78, 0x1e, 0x00, + 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0x00, 0x78, 0x1e, 0x00, 0x00, 0x70, 0x0e, + 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, + }; + + static BCursor CrossCursor = { + /*small*/ + cross_sbm, + cross_smsk, + 16, + 16, + 7, + 7, + /*big*/ + cross_lbm, + cross_lmsk, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_CROSSCURSOR] = &CrossCursor; + END_CURSOR_BLOCK + + /********************** EditCross Cursor ***********************/ + BEGIN_CURSOR_BLOCK + static char editcross_sbm[] = { + 0x0e, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x19, 0x03, 0x1d, 0x03, 0x11, + 0x03, 0x0e, 0x03, 0x00, 0x03, 0xf8, 0x7c, 0xf8, 0x7c, 0x00, 0x03, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, + }; + + static char editcross_smsk[] = { + 0x0e, 0x00, 0x1f, 0x00, 0x1f, 0x03, 0x1f, 0x03, 0x1f, 0x03, 0x1f, + 0x03, 0x0e, 0x03, 0x80, 0x07, 0xfc, 0xfc, 0xfc, 0xfc, 0x80, 0x07, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, + }; + + static BCursor EditCrossCursor = { + /*small*/ + editcross_sbm, + editcross_smsk, + 16, + 16, + 9, + 8, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_EDITCROSSCURSOR] = &EditCrossCursor; + END_CURSOR_BLOCK + + /********************** Box Select *************************/ + BEGIN_CURSOR_BLOCK + static char box_sbm[32] = { + 0x7f, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x06, 0x41, 0x06, 0x41, + 0x06, 0x7f, 0x06, 0x00, 0x06, 0xe0, 0x79, 0xe0, 0x79, 0x00, 0x06, + 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, + }; + + static char box_smsk[32] = { + 0x7f, 0x00, 0x7f, 0x00, 0x63, 0x06, 0x63, 0x06, 0x63, 0x06, 0x7f, + 0x06, 0x7f, 0x06, 0x00, 0x0f, 0xf0, 0xf9, 0xf0, 0xf9, 0x00, 0x0f, + 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, + }; + + static BCursor BoxSelCursor = { + /*small*/ + box_sbm, + box_smsk, + 16, + 16, + 9, + 8, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_BOXSELCURSOR] = &BoxSelCursor; + + END_CURSOR_BLOCK + /********************** Knife Cursor ***********************/ + BEGIN_CURSOR_BLOCK + static char knife_sbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x2c, 0x00, 0x5a, 0x00, + 0x34, 0x00, 0x2a, 0x00, 0x17, 0x80, 0x06, 0x40, 0x03, 0xa0, 0x03, + 0xd0, 0x01, 0x68, 0x00, 0x1c, 0x00, 0x06, 0x00, 0x00, 0x00, + }; + + static char knife_smsk[] = { + 0x00, 0x60, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0xfe, 0x00, 0xfe, 0x00, + 0x7e, 0x00, 0x7f, 0x80, 0x3f, 0xc0, 0x0e, 0x60, 0x07, 0xb0, 0x07, + 0xd8, 0x03, 0xec, 0x01, 0x7e, 0x00, 0x1f, 0x00, 0x07, 0x00, + }; + + static char knife_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x7f, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0xc0, 0x5f, 0x00, 0x00, 0xc0, 0x6f, 0x00, + 0x00, 0xc0, 0x37, 0x00, 0x00, 0xa8, 0x1b, 0x00, 0x00, 0x54, 0x0d, 0x00, 0x00, 0xa8, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0xc0, 0x07, + 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xd0, 0x0f, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00, 0xf4, + 0x07, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x80, 0x0e, 0x00, 0x00, 0xc0, + 0x03, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static char knife_lmsk[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x80, 0xff, 0x00, 0x00, 0xc0, 0xbf, 0x00, 0x00, 0xe0, 0xdf, 0x00, 0x00, 0xe0, 0xef, 0x00, + 0x00, 0xf8, 0x77, 0x00, 0x00, 0xfc, 0x3b, 0x00, 0x00, 0xfe, 0x1d, 0x00, 0x00, 0xfe, 0x0f, + 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x00, 0x00, 0xe0, 0x7f, + 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xd8, 0x1f, 0x00, 0x00, 0xec, 0x0f, 0x00, 0x00, 0xf6, + 0x0f, 0x00, 0x00, 0xfb, 0x06, 0x00, 0x80, 0xbd, 0x01, 0x00, 0xc0, 0x6e, 0x00, 0x00, 0xe0, + 0x1b, 0x00, 0x00, 0xf0, 0x06, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static BCursor KnifeCursor = { + /*small*/ + knife_sbm, + knife_smsk, + 16, + 16, + 0, + 15, + /*big*/ + knife_lbm, + knife_lmsk, + 32, + 32, + 0, + 31, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_KNIFECURSOR] = &KnifeCursor; + + END_CURSOR_BLOCK + + /********************** Loop Select Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char vloop_sbm[] = { + 0x00, 0x00, 0x7e, 0x00, 0x3e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x66, + 0x60, 0x62, 0x6f, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x00, 0x00, 0x60, 0x60, 0x60, 0x6f, 0x00, 0x00, + }; + + static char vloop_smsk[] = { + 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00, 0xff, 0xf0, 0xff, + 0xff, 0xf7, 0xff, 0xf3, 0xf0, 0x61, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xff, 0xf0, 0xf0, + }; + + static char vloop_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, + 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfc, 0x03, + 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x3c, 0x3c, + 0x3c, 0x00, 0x3c, 0x0c, 0x3c, 0xff, 0x3c, 0x0c, 0x3c, 0xff, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, + 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, + 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0xff, 0x3c, 0x00, 0x3c, 0xff, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static char vloop_lmsk[] = { + 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, + 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x00, 0xff, + 0x0f, 0xff, 0x00, 0xff, 0x03, 0x3c, 0x00, 0x3c, 0x03, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, + 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, + 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, + 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + }; + + static BCursor VLoopCursor = { + /*small*/ + vloop_sbm, + vloop_smsk, + 16, + 16, + 0, + 0, + /*big*/ + vloop_lbm, + vloop_lmsk, + 32, + 32, + 0, + 0, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_VLOOPCURSOR] = &VLoopCursor; + + END_CURSOR_BLOCK + + /********************** TextEdit Cursor ***********************/ + BEGIN_CURSOR_BLOCK + static char textedit_sbm[] = { + 0xe0, 0x03, 0x10, 0x04, 0x60, 0x03, 0x40, 0x01, 0x40, 0x01, 0x40, + 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, + 0x40, 0x01, 0x40, 0x01, 0x60, 0x03, 0x10, 0x04, 0xe0, 0x03, + }; + + static char textedit_smsk[] = { + 0xe0, 0x03, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0xc0, 0x01, 0xc0, + 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xe0, 0x03, + }; + + static BCursor TextEditCursor = { + /*small*/ + textedit_sbm, + textedit_smsk, + 16, + 16, + 9, + 8, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_TEXTEDITCURSOR] = &TextEditCursor; + END_CURSOR_BLOCK + + /********************** Paintbrush Cursor ***********************/ + BEGIN_CURSOR_BLOCK + static char paintbrush_sbm[] = { + + 0x00, 0xe0, 0x00, 0x98, 0x00, 0x44, 0x00, 0x42, 0x00, 0x21, 0x80, + 0x20, 0x40, 0x13, 0x40, 0x17, 0xa0, 0x0b, 0x98, 0x05, 0x04, 0x02, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x81, 0x00, 0x7f, 0x00, + }; + + static char paintbrush_smsk[] = { + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x7c, 0x00, 0x7e, 0x00, 0x3f, 0x80, + 0x3f, 0xc0, 0x1f, 0xc0, 0x1f, 0xe0, 0x0f, 0xf8, 0x07, 0xfc, 0x03, + 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xff, 0x00, 0x7f, 0x00, + }; + + static BCursor PaintBrushCursor = { + /*small*/ + paintbrush_sbm, + paintbrush_smsk, + 16, + 16, + 0, + 15, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_PAINTBRUSHCURSOR] = &PaintBrushCursor; + END_CURSOR_BLOCK + + /********************** Hand Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char hand_sbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x0d, 0x98, 0x6d, 0x98, + 0x6d, 0xb0, 0x6d, 0xb0, 0x6d, 0xe0, 0x6f, 0xe6, 0x7f, 0xee, 0x7f, + 0xfc, 0x3f, 0xf8, 0x3f, 0xf0, 0x1f, 0xc0, 0x1f, 0xc0, 0x1f, + }; + + static char hand_smsk[] = { + 0x00, 0x00, 0x80, 0x01, 0xc0, 0x0f, 0xd8, 0x7f, 0xfc, 0xff, 0xfc, + 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0x7f, 0xfc, 0x7f, 0xf8, 0x3f, 0xf0, 0x3f, 0xe0, 0x3f, + }; + + static BCursor HandCursor = { + /*small*/ + hand_sbm, + hand_smsk, + 16, + 16, + 8, + 8, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_HANDCURSOR] = &HandCursor; + + END_CURSOR_BLOCK + + /********************** NSEW Scroll Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char nsewscroll_sbm[] = { + 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xc0, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x30, 0x0e, 0x70, 0x0e, 0x70, 0x0c, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00, + }; + + static char nsewscroll_smsk[] = { + 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xe0, 0x07, 0xc0, 0x03, 0x0c, + 0x30, 0x1e, 0x78, 0x1f, 0xf8, 0x1f, 0xf8, 0x1e, 0x78, 0x0c, 0x30, + 0xc0, 0x03, 0xe0, 0x07, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, + }; + + static BCursor NSEWScrollCursor = { + /*small*/ + nsewscroll_sbm, + nsewscroll_smsk, + 16, + 16, + 8, + 8, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_NSEW_SCROLLCURSOR] = &NSEWScrollCursor; + + END_CURSOR_BLOCK + + /********************** NS Scroll Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char nsscroll_sbm[] = { + 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xc0, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00, + }; + + static char nsscroll_smsk[] = { + 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xe0, 0x07, 0xc0, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x03, 0xe0, 0x07, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, + }; + + static BCursor NSScrollCursor = { + /*small*/ + nsscroll_sbm, + nsscroll_smsk, + 16, + 16, + 8, + 8, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_NS_SCROLLCURSOR] = &NSScrollCursor; + + END_CURSOR_BLOCK + + /********************** EW Scroll Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char ewscroll_sbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x30, 0x0e, 0x70, 0x0e, 0x70, 0x0c, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static char ewscroll_smsk[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x30, 0x1e, 0x78, 0x1f, 0xf8, 0x1f, 0xf8, 0x1e, 0x78, 0x0c, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static BCursor EWScrollCursor = { + /*small*/ + ewscroll_sbm, + ewscroll_smsk, + 16, + 16, + 8, + 8, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_EW_SCROLLCURSOR] = &EWScrollCursor; + + END_CURSOR_BLOCK + + /********************** Eyedropper Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char eyedropper_sbm[] = { + 0x00, 0x30, 0x00, 0x48, 0x00, 0x85, 0x80, 0x82, 0x40, 0x40, 0x80, + 0x20, 0x40, 0x11, 0xa0, 0x23, 0xd0, 0x15, 0xe8, 0x0a, 0x74, 0x01, + 0xb4, 0x00, 0x4a, 0x00, 0x35, 0x00, 0x08, 0x00, 0x04, 0x00, + }; + + static char eyedropper_smsk[] = { + 0x00, 0x30, 0x00, 0x78, 0x00, 0xfd, 0x80, 0xff, 0xc0, 0x7f, 0x80, + 0x3f, 0xc0, 0x1f, 0xe0, 0x3f, 0xf0, 0x1f, 0xf8, 0x0b, 0xfc, 0x01, + 0xfc, 0x00, 0x7e, 0x00, 0x3f, 0x00, 0x0c, 0x00, 0x04, 0x00, + }; + + static BCursor EyedropperCursor = { + /*small*/ + eyedropper_sbm, + eyedropper_smsk, + 16, + 16, + 1, + 15, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE, + }; + + BlenderCursor[BC_EYEDROPPER_CURSOR] = &EyedropperCursor; + + END_CURSOR_BLOCK + + /********************** Swap Area Cursor ***********************/ + BEGIN_CURSOR_BLOCK + static char swap_sbm[] = { + 0xc0, 0xff, 0x40, 0x80, 0x40, 0x80, 0x40, 0x9c, 0x40, 0x98, 0x40, + 0x94, 0x00, 0x82, 0xfe, 0x80, 0x7e, 0xfd, 0xbe, 0x01, 0xda, 0x01, + 0xe2, 0x01, 0xe2, 0x01, 0xc2, 0x01, 0xfe, 0x01, 0x00, 0x00, + }; + + static char swap_smsk[] = { + 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0x03, + 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, + }; + + static BCursor SwapCursor = { + /*small*/ + swap_sbm, + swap_smsk, + 16, + 16, + 8, + 8, + /*big*/ + NULL, + NULL, + 32, + 32, + 15, + 15, + /*color*/ + BC_YELLOW, + BC_BLUE, + }; + + BlenderCursor[BC_SWAPAREA_CURSOR] = &SwapCursor; + + END_CURSOR_BLOCK + + /********************** Horizontal Split Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char hsplit_sbm[] = {0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x88, + 0x08, 0x8C, 0x18, 0x8E, 0x38, 0x8C, 0x18, 0x88, 0x08, 0x80, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char hsplit_smsk[] = {0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xD0, 0x05, 0xD8, 0x0D, 0xDC, + 0x1D, 0xDE, 0x3D, 0xDF, 0x7D, 0xDE, 0x3D, 0xDC, 0x1D, 0xD8, 0x0D, + 0xD0, 0x05, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00}; + + static char hsplit_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x84, 0x21, 0x00, 0x00, 0x86, 0x61, 0x00, 0x00, 0x87, 0xE1, 0x00, 0x80, + 0x87, 0xE1, 0x01, 0xC0, 0x87, 0xE1, 0x03, 0xE0, 0x87, 0xE1, 0x07, 0xF0, 0x87, 0xE1, 0x0F, + 0xF8, 0x87, 0xE1, 0x1F, 0xF0, 0x87, 0xE1, 0x0F, 0xE0, 0x87, 0xE1, 0x07, 0xC0, 0x87, 0xE1, + 0x03, 0x80, 0x87, 0xE1, 0x01, 0x00, 0x87, 0xE1, 0x00, 0x00, 0x86, 0x61, 0x00, 0x00, 0x84, + 0x21, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char hsplit_lmsk[] = { + 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, + 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC8, 0x13, 0x00, 0x00, 0xCC, 0x33, 0x00, 0x00, 0xCE, + 0x73, 0x00, 0x00, 0xCF, 0xF3, 0x00, 0x80, 0xCF, 0xF3, 0x01, 0xC0, 0xCF, 0xF3, 0x03, 0xE0, + 0xCF, 0xF3, 0x07, 0xF0, 0xCF, 0xF3, 0x0F, 0xF8, 0xCF, 0xF3, 0x1F, 0xFC, 0xCF, 0xF3, 0x3F, + 0xFE, 0xCF, 0xF3, 0x7F, 0xFC, 0xCF, 0xF3, 0x3F, 0xF8, 0xCF, 0xF3, 0x1F, 0xF0, 0xCF, 0xF3, + 0x0F, 0xE0, 0xCF, 0xF3, 0x07, 0xC0, 0xCF, 0xF3, 0x03, 0x80, 0xCF, 0xF3, 0x01, 0x00, 0xCF, + 0xF3, 0x00, 0x00, 0xCE, 0x73, 0x00, 0x00, 0xCC, 0x33, 0x00, 0x00, 0xC8, 0x13, 0x00, 0x00, + 0xC8, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, + 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static BCursor HSplitCursor = {/*small*/ + hsplit_sbm, + hsplit_smsk, + 16, + 16, + 7, + 7, + /*big*/ + hsplit_lbm, + hsplit_lmsk, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE}; + + BlenderCursor[BC_H_SPLITCURSOR] = &HSplitCursor; + + END_CURSOR_BLOCK + + /********************** Vertical Split Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char vsplit_sbm[] = {0x00, 0x00, 0x80, 0x00, 0xC0, 0x01, 0xE0, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char vsplit_smsk[] = {0x80, 0x00, 0xC0, 0x01, 0xE0, 0x03, 0xF0, 0x07, 0xF8, 0x0F, 0x00, + 0x00, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F, 0x00, 0x00, 0xF8, 0x0F, + 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00}; + + static char vsplit_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xF8, + 0x0F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0xFF, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xFE, + 0x3F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, + 0xE0, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char vsplit_lmsk[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xE0, 0x03, + 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFE, + 0x3F, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0x01, 0xE0, + 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, + 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0x01, 0x80, 0xFF, + 0xFF, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, + 0xF8, 0x0F, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static BCursor VSplitCursor = {/*small*/ + vsplit_sbm, + vsplit_smsk, + 16, + 16, + 7, + 7, + /*big*/ + vsplit_lbm, + vsplit_lmsk, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE}; + + BlenderCursor[BC_V_SPLITCURSOR] = &VSplitCursor; + + END_CURSOR_BLOCK + + /********************** North Arrow Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char narrow_sbm[] = {0x00, 0x00, 0x80, 0x00, 0xC0, 0x01, 0xE0, 0x03, 0xF0, 0x07, 0xF8, + 0x0F, 0xFC, 0x1F, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char narrow_smsk[] = {0x80, 0x00, 0xC0, 0x01, 0xE0, 0x03, 0xF0, 0x07, 0xF8, 0x0F, 0xFC, + 0x1F, 0xFE, 0x3F, 0xFF, 0x7F, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, + 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char narrow_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x01, + 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xFC, + 0x1F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0xC0, + 0xFF, 0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x0F, + 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, + 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, + 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char narrow_lmsk[] = { + 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF0, 0x07, + 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFF, + 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x03, 0xF0, + 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF, 0xFF, 0x3F, + 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, + 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, + 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static BCursor NArrowCursor = {/*small*/ + narrow_sbm, + narrow_smsk, + 16, + 16, + 7, + 4, + /*big*/ + narrow_lbm, + narrow_lmsk, + 32, + 32, + 15, + 10, + /*color*/ + BC_BLACK, + BC_WHITE}; + + BlenderCursor[BC_N_ARROWCURSOR] = &NArrowCursor; + + END_CURSOR_BLOCK + + /********************** South Arrow Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char sarrow_sbm[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, + 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xFC, 0x1F, 0xF8, 0x0F, + 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00}; + + static char sarrow_smsk[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0xF0, + 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xFF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, + 0xF8, 0x0F, 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00}; + + static char sarrow_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, + 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, + 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, + 0x07, 0xE0, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xFF, + 0x7F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, + 0xF0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char sarrow_lmsk[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, + 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, + 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, + 0x00, 0xFE, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, + 0x1F, 0xF8, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, + 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, + 0xFC, 0x1F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0x00, + 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00}; + + static BCursor SArrowCursor = {/*small*/ + sarrow_sbm, + sarrow_smsk, + 16, + 16, + 7, + 11, + /*big*/ + sarrow_lbm, + sarrow_lmsk, + 32, + 32, + 15, + 21, + /*color*/ + BC_BLACK, + BC_WHITE}; + + BlenderCursor[BC_S_ARROWCURSOR] = &SArrowCursor; + + END_CURSOR_BLOCK + + /********************** East Arrow Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char earrow_sbm[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0E, 0xE0, + 0x1F, 0xE0, 0x3F, 0xE0, 0x7F, 0xE0, 0x3F, 0xE0, 0x1F, 0x00, 0x0E, + 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char earrow_smsk[] = {0x00, 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0F, 0xF0, 0x1F, 0xF0, + 0x3F, 0xF0, 0x7F, 0xF0, 0xFF, 0xF0, 0x7F, 0xF0, 0x3F, 0xF0, 0x1F, + 0x00, 0x0F, 0x00, 0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00}; + + static char earrow_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, + 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x1F, + 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, + 0x07, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char earrow_lmsk[] = { + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0F, + 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0x07, 0x80, + 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xFF, 0x1F, 0x80, 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0x7F, + 0x80, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x7F, 0x80, 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, + 0x1F, 0x80, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xFF, 0x07, 0x80, 0xFF, 0xFF, 0x03, 0x00, 0x00, + 0xFF, 0x01, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static BCursor EArrowCursor = {/*small*/ + earrow_sbm, + earrow_smsk, + 16, + 16, + 11, + 7, + /*big*/ + earrow_lbm, + earrow_lmsk, + 32, + 32, + 15, + 22, + /*color*/ + BC_BLACK, + BC_WHITE}; + + BlenderCursor[BC_E_ARROWCURSOR] = &EArrowCursor; + + END_CURSOR_BLOCK + + /********************** West Arrow Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char warrow_sbm[] = {0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0xF8, + 0x07, 0xFC, 0x07, 0xFE, 0x07, 0xFC, 0x07, 0xF8, 0x07, 0x70, 0x00, + 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char warrow_smsk[] = {0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0xF8, 0x0F, 0xFC, + 0x0F, 0xFE, 0x0F, 0xFF, 0x0F, 0xFE, 0x0F, 0xFC, 0x0F, 0xF8, 0x0F, + 0xF0, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x00}; + + static char warrow_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0xC0, + 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0x00, + 0xFC, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, + 0x00, 0xC0, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7E, + 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char warrow_lmsk[] = { + 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x80, 0xFF, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x01, 0xF0, + 0xFF, 0xFF, 0x01, 0xF8, 0xFF, 0xFF, 0x01, 0xFC, 0xFF, 0xFF, 0x01, 0xFE, 0xFF, 0xFF, 0x01, + 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0xFF, 0xFF, 0x01, 0xFC, 0xFF, 0xFF, 0x01, 0xF8, 0xFF, 0xFF, + 0x01, 0xF0, 0xFF, 0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x01, 0xC0, 0xFF, 0xFF, 0x01, 0x80, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static BCursor WArrowCursor = {/*small*/ + warrow_sbm, + warrow_smsk, + 16, + 16, + 4, + 7, + /*big*/ + warrow_lbm, + warrow_lmsk, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE}; + + BlenderCursor[BC_W_ARROWCURSOR] = &WArrowCursor; + + END_CURSOR_BLOCK + + /********************** Stop Sign Cursor ***********************/ + BEGIN_CURSOR_BLOCK + + static char stop_sbm[] = {0x00, 0x00, 0xE0, 0x07, 0x38, 0x1C, 0x1C, 0x30, 0x3C, 0x20, 0x76, + 0x60, 0xE2, 0x40, 0xC2, 0x41, 0x82, 0x43, 0x02, 0x47, 0x06, 0x6E, + 0x04, 0x3C, 0x0C, 0x38, 0x38, 0x1C, 0xE0, 0x07, 0x00, 0x00}; + + static char stop_smsk[] = {0xE0, 0x07, 0xF8, 0x1F, 0xFC, 0x3F, 0x3E, 0x7C, 0x7E, 0x70, 0xFF, + 0xF0, 0xF7, 0xE1, 0xE7, 0xE3, 0xC7, 0xE7, 0x87, 0xEF, 0x0F, 0xFF, + 0x0E, 0x7E, 0x3E, 0x7C, 0xFC, 0x3F, 0xF8, 0x1F, 0xE0, 0x07}; + + static char stop_lbm[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0xFE, 0x7F, 0x00, 0x00, 0x0F, 0xF0, + 0x00, 0xC0, 0x03, 0xC0, 0x03, 0xE0, 0x01, 0x00, 0x07, 0xF0, 0x01, 0x00, 0x0E, 0xF0, 0x01, + 0x00, 0x0C, 0xF8, 0x03, 0x00, 0x18, 0x1C, 0x07, 0x00, 0x38, 0x0C, 0x0E, 0x00, 0x30, 0x0C, + 0x1C, 0x00, 0x30, 0x06, 0x38, 0x00, 0x60, 0x06, 0x70, 0x00, 0x60, 0x06, 0xE0, 0x00, 0x60, + 0x06, 0xC0, 0x01, 0x60, 0x06, 0x80, 0x03, 0x60, 0x06, 0x00, 0x07, 0x60, 0x06, 0x00, 0x0E, + 0x60, 0x06, 0x00, 0x1C, 0x60, 0x0C, 0x00, 0x38, 0x30, 0x0C, 0x00, 0x70, 0x30, 0x1C, 0x00, + 0xE0, 0x38, 0x18, 0x00, 0xC0, 0x1F, 0x30, 0x00, 0x80, 0x0F, 0x70, 0x00, 0x80, 0x0F, 0xE0, + 0x00, 0x80, 0x07, 0xC0, 0x03, 0xC0, 0x03, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFE, 0x7F, 0x00, + 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static char stop_lmsk[] = { + 0x00, 0xF0, 0x0F, 0x00, 0x00, 0xFE, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0x01, 0xC0, 0xFF, 0xFF, + 0x03, 0xE0, 0x1F, 0xF8, 0x07, 0xF0, 0x03, 0xC0, 0x0F, 0xF8, 0x03, 0x80, 0x1F, 0xFC, 0x07, + 0x00, 0x3F, 0xFC, 0x0F, 0x00, 0x3E, 0xFE, 0x1F, 0x00, 0x7C, 0x9E, 0x3F, 0x00, 0x78, 0x1E, + 0x7F, 0x00, 0x78, 0x1F, 0xFE, 0x00, 0xF8, 0x0F, 0xFC, 0x01, 0xF0, 0x0F, 0xF8, 0x03, 0xF0, + 0x0F, 0xF0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xC0, 0x1F, 0xF0, 0x0F, 0x80, 0x3F, + 0xF0, 0x1F, 0x00, 0x7F, 0xF8, 0x1E, 0x00, 0xFE, 0x78, 0x1E, 0x00, 0xFC, 0x79, 0x3E, 0x00, + 0xF8, 0x7F, 0x7C, 0x00, 0xF0, 0x3F, 0xFC, 0x00, 0xE0, 0x3F, 0xF8, 0x01, 0xC0, 0x1F, 0xF0, + 0x03, 0xC0, 0x0F, 0xE0, 0x1F, 0xF8, 0x07, 0xC0, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0x01, + 0x00, 0xFE, 0x7F, 0x00, 0x00, 0xF0, 0x0F, 0x00}; + + static BCursor StopCursor = {/*small*/ + stop_sbm, + stop_smsk, + 16, + 16, + 7, + 7, + /*big*/ + stop_lbm, + stop_lmsk, + 32, + 32, + 15, + 15, + /*color*/ + BC_BLACK, + BC_WHITE}; + + BlenderCursor[BC_STOPCURSOR] = &StopCursor; + + END_CURSOR_BLOCK + + /********************** Put the cursors in the array ***********************/ } diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 92ce9957351..30311d83509 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -63,429 +63,438 @@ static ListBase dropboxes = {NULL, NULL}; /* when editors become configurable, they can add own dropbox definitions */ typedef struct wmDropBoxMap { - struct wmDropBoxMap *next, *prev; + struct wmDropBoxMap *next, *prev; - ListBase dropboxes; - short spaceid, regionid; - char idname[KMAP_MAX_NAME]; + ListBase dropboxes; + short spaceid, regionid; + char idname[KMAP_MAX_NAME]; } wmDropBoxMap; /* spaceid/regionid is zero for window drop maps */ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid) { - wmDropBoxMap *dm; - - for (dm = dropboxes.first; dm; dm = dm->next) { - if (dm->spaceid == spaceid && dm->regionid == regionid) { - if (STREQLEN(idname, dm->idname, KMAP_MAX_NAME)) { - return &dm->dropboxes; - } - } - } - - dm = MEM_callocN(sizeof(struct wmDropBoxMap), "dropmap list"); - BLI_strncpy(dm->idname, idname, KMAP_MAX_NAME); - dm->spaceid = spaceid; - dm->regionid = regionid; - BLI_addtail(&dropboxes, dm); - - return &dm->dropboxes; + wmDropBoxMap *dm; + + for (dm = dropboxes.first; dm; dm = dm->next) { + if (dm->spaceid == spaceid && dm->regionid == regionid) { + if (STREQLEN(idname, dm->idname, KMAP_MAX_NAME)) { + return &dm->dropboxes; + } + } + } + + dm = MEM_callocN(sizeof(struct wmDropBoxMap), "dropmap list"); + BLI_strncpy(dm->idname, idname, KMAP_MAX_NAME); + dm->spaceid = spaceid; + dm->regionid = regionid; + BLI_addtail(&dropboxes, dm); + + return &dm->dropboxes; } - - -wmDropBox *WM_dropbox_add( - ListBase *lb, const char *idname, - bool (*poll)(bContext *, wmDrag *, const wmEvent *, const char **), - void (*copy)(wmDrag *, wmDropBox *)) +wmDropBox *WM_dropbox_add(ListBase *lb, + const char *idname, + bool (*poll)(bContext *, wmDrag *, const wmEvent *, const char **), + void (*copy)(wmDrag *, wmDropBox *)) { - wmDropBox *drop = MEM_callocN(sizeof(wmDropBox), "wmDropBox"); + wmDropBox *drop = MEM_callocN(sizeof(wmDropBox), "wmDropBox"); - drop->poll = poll; - drop->copy = copy; - drop->ot = WM_operatortype_find(idname, 0); - drop->opcontext = WM_OP_INVOKE_DEFAULT; + drop->poll = poll; + drop->copy = copy; + drop->ot = WM_operatortype_find(idname, 0); + drop->opcontext = WM_OP_INVOKE_DEFAULT; - if (drop->ot == NULL) { - MEM_freeN(drop); - printf("Error: dropbox with unknown operator: %s\n", idname); - return NULL; - } - WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname); + if (drop->ot == NULL) { + MEM_freeN(drop); + printf("Error: dropbox with unknown operator: %s\n", idname); + return NULL; + } + WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname); - BLI_addtail(lb, drop); + BLI_addtail(lb, drop); - return drop; + return drop; } void wm_dropbox_free(void) { - wmDropBoxMap *dm; + wmDropBoxMap *dm; - for (dm = dropboxes.first; dm; dm = dm->next) { - wmDropBox *drop; + for (dm = dropboxes.first; dm; dm = dm->next) { + wmDropBox *drop; - for (drop = dm->dropboxes.first; drop; drop = drop->next) { - if (drop->ptr) { - WM_operator_properties_free(drop->ptr); - MEM_freeN(drop->ptr); - } - } - BLI_freelistN(&dm->dropboxes); - } + for (drop = dm->dropboxes.first; drop; drop = drop->next) { + if (drop->ptr) { + WM_operator_properties_free(drop->ptr); + MEM_freeN(drop->ptr); + } + } + BLI_freelistN(&dm->dropboxes); + } - BLI_freelistN(&dropboxes); + BLI_freelistN(&dropboxes); } /* *********************************** */ /* note that the pointer should be valid allocated and not on stack */ -wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags) +wmDrag *WM_event_start_drag( + struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags) { - wmWindowManager *wm = CTX_wm_manager(C); - wmDrag *drag = MEM_callocN(sizeof(struct wmDrag), "new drag"); - - /* keep track of future multitouch drag too, add a mousepointer id or so */ - /* if multiple drags are added, they're drawn as list */ - - BLI_addtail(&wm->drags, drag); - drag->flags = flags; - drag->icon = icon; - drag->type = type; - if (type == WM_DRAG_PATH) { - BLI_strncpy(drag->path, poin, FILE_MAX); - } - else if (type == WM_DRAG_ID) { - if (poin) { - WM_drag_add_ID(drag, poin, NULL); - } - } - else { - drag->poin = poin; - } - drag->value = value; - - return drag; + wmWindowManager *wm = CTX_wm_manager(C); + wmDrag *drag = MEM_callocN(sizeof(struct wmDrag), "new drag"); + + /* keep track of future multitouch drag too, add a mousepointer id or so */ + /* if multiple drags are added, they're drawn as list */ + + BLI_addtail(&wm->drags, drag); + drag->flags = flags; + drag->icon = icon; + drag->type = type; + if (type == WM_DRAG_PATH) { + BLI_strncpy(drag->path, poin, FILE_MAX); + } + else if (type == WM_DRAG_ID) { + if (poin) { + WM_drag_add_ID(drag, poin, NULL); + } + } + else { + drag->poin = poin; + } + drag->value = value; + + return drag; } void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy) { - drag->imb = imb; - drag->scale = scale; - drag->sx = sx; - drag->sy = sy; + drag->imb = imb; + drag->scale = scale; + drag->sx = sx; + drag->sy = sy; } void WM_drag_free(wmDrag *drag) { - if ((drag->flags & WM_DRAG_FREE_DATA) && drag->poin) { - MEM_freeN(drag->poin); - } + if ((drag->flags & WM_DRAG_FREE_DATA) && drag->poin) { + MEM_freeN(drag->poin); + } - BLI_freelistN(&drag->ids); - MEM_freeN(drag); + BLI_freelistN(&drag->ids); + MEM_freeN(drag); } void WM_drag_free_list(struct ListBase *lb) { - wmDrag *drag; - while ((drag = BLI_pophead(lb))) { - WM_drag_free(drag); - } + wmDrag *drag; + while ((drag = BLI_pophead(lb))) { + WM_drag_free(drag); + } } - -static const char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, const wmEvent *event) +static const char *dropbox_active(bContext *C, + ListBase *handlers, + wmDrag *drag, + const wmEvent *event) { - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) { - wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base; - if (handler->dropboxes) { - for (wmDropBox *drop = handler->dropboxes->first; drop; drop = drop->next) { - const char *tooltip = NULL; - if (drop->poll(C, drag, event, &tooltip)) { - /* XXX Doing translation here might not be ideal, but later we have no more - * access to ot (and hence op context)... */ - return (tooltip) ? tooltip : RNA_struct_ui_name(drop->ot->srna); - } - } - } - } - } - return NULL; + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { + if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) { + wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base; + if (handler->dropboxes) { + for (wmDropBox *drop = handler->dropboxes->first; drop; drop = drop->next) { + const char *tooltip = NULL; + if (drop->poll(C, drag, event, &tooltip)) { + /* XXX Doing translation here might not be ideal, but later we have no more + * access to ot (and hence op context)... */ + return (tooltip) ? tooltip : RNA_struct_ui_name(drop->ot->srna); + } + } + } + } + } + return NULL; } /* return active operator name when mouse is in box */ static const char *wm_dropbox_active(bContext *C, wmDrag *drag, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); - const char *name; - - name = dropbox_active(C, &win->handlers, drag, event); - if (name) { - return name; - } - - name = dropbox_active(C, &sa->handlers, drag, event); - if (name) { - return name; - } - - name = dropbox_active(C, &ar->handlers, drag, event); - if (name) { - return name; - } - - return NULL; + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + const char *name; + + name = dropbox_active(C, &win->handlers, drag, event); + if (name) { + return name; + } + + name = dropbox_active(C, &sa->handlers, drag, event); + if (name) { + return name; + } + + name = dropbox_active(C, &ar->handlers, drag, event); + if (name) { + return name; + } + + return NULL; } - static void wm_drop_operator_options(bContext *C, wmDrag *drag, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); - - /* for multiwin drags, we only do this if mouse inside */ - if (event->x < 0 || event->y < 0 || event->x > winsize_x || event->y > winsize_y) { - return; - } - - drag->opname[0] = 0; - - /* check buttons (XXX todo rna and value) */ - if (UI_but_active_drop_name(C)) { - BLI_strncpy(drag->opname, IFACE_("Paste name"), sizeof(drag->opname)); - } - else { - const char *opname = wm_dropbox_active(C, drag, event); - - if (opname) { - BLI_strncpy(drag->opname, opname, sizeof(drag->opname)); - // WM_cursor_modal_set(win, CURSOR_COPY); - } - // else - // WM_cursor_modal_restore(win); - /* unsure about cursor type, feels to be too much */ - } + wmWindow *win = CTX_wm_window(C); + const int winsize_x = WM_window_pixels_x(win); + const int winsize_y = WM_window_pixels_y(win); + + /* for multiwin drags, we only do this if mouse inside */ + if (event->x < 0 || event->y < 0 || event->x > winsize_x || event->y > winsize_y) { + return; + } + + drag->opname[0] = 0; + + /* check buttons (XXX todo rna and value) */ + if (UI_but_active_drop_name(C)) { + BLI_strncpy(drag->opname, IFACE_("Paste name"), sizeof(drag->opname)); + } + else { + const char *opname = wm_dropbox_active(C, drag, event); + + if (opname) { + BLI_strncpy(drag->opname, opname, sizeof(drag->opname)); + // WM_cursor_modal_set(win, CURSOR_COPY); + } + // else + // WM_cursor_modal_restore(win); + /* unsure about cursor type, feels to be too much */ + } } /* called in inner handler loop, region context */ void wm_drags_check_ops(bContext *C, const wmEvent *event) { - wmWindowManager *wm = CTX_wm_manager(C); - wmDrag *drag; + wmWindowManager *wm = CTX_wm_manager(C); + wmDrag *drag; - for (drag = wm->drags.first; drag; drag = drag->next) { - wm_drop_operator_options(C, drag, event); - } + for (drag = wm->drags.first; drag; drag = drag->next) { + wm_drop_operator_options(C, drag, event); + } } /* ************** IDs ***************** */ void WM_drag_add_ID(wmDrag *drag, ID *id, ID *from_parent) { - /* Don't drag the same ID twice. */ - for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) { - if (drag_id->id == id) { - if (drag_id->from_parent == NULL) { - drag_id->from_parent = from_parent; - } - return; - } - else if (GS(drag_id->id->name) != GS(id->name)) { - BLI_assert(!"All dragged IDs must have the same type"); - return; - } - } - - /* Add to list. */ - wmDragID *drag_id = MEM_callocN(sizeof(wmDragID), __func__); - drag_id->id = id; - drag_id->from_parent = from_parent; - BLI_addtail(&drag->ids, drag_id); + /* Don't drag the same ID twice. */ + for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) { + if (drag_id->id == id) { + if (drag_id->from_parent == NULL) { + drag_id->from_parent = from_parent; + } + return; + } + else if (GS(drag_id->id->name) != GS(id->name)) { + BLI_assert(!"All dragged IDs must have the same type"); + return; + } + } + + /* Add to list. */ + wmDragID *drag_id = MEM_callocN(sizeof(wmDragID), __func__); + drag_id->id = id; + drag_id->from_parent = from_parent; + BLI_addtail(&drag->ids, drag_id); } ID *WM_drag_ID(const wmDrag *drag, short idcode) { - if (drag->type != WM_DRAG_ID) { - return NULL; - } - - wmDragID *drag_id = drag->ids.first; - if (!drag_id) { - return NULL; - } + if (drag->type != WM_DRAG_ID) { + return NULL; + } - ID *id = drag_id->id; - return (idcode == 0 || GS(id->name) == idcode) ? id : NULL; + wmDragID *drag_id = drag->ids.first; + if (!drag_id) { + return NULL; + } + ID *id = drag_id->id; + return (idcode == 0 || GS(id->name) == idcode) ? id : NULL; } ID *WM_drag_ID_from_event(const wmEvent *event, short idcode) { - if (event->custom != EVT_DATA_DRAGDROP) { - return NULL; - } + if (event->custom != EVT_DATA_DRAGDROP) { + return NULL; + } - ListBase *lb = event->customdata; - return WM_drag_ID(lb->first, idcode); + ListBase *lb = event->customdata; + return WM_drag_ID(lb->first, idcode); } /* ************** draw ***************** */ static void wm_drop_operator_draw(const char *name, int x, int y) { - const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; - const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f}; + const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; + const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f}; - UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg); + UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg); } static const char *wm_drag_name(wmDrag *drag) { - switch (drag->type) { - case WM_DRAG_ID: - { - ID *id = WM_drag_ID(drag, 0); - bool single = (BLI_listbase_count_at_most(&drag->ids, 2) == 1); - - if (single) { - return id->name + 2; - } - else if (id) { - return BKE_idcode_to_name_plural(GS(id->name)); - } - break; - } - case WM_DRAG_PATH: - case WM_DRAG_NAME: - return drag->path; - } - return ""; + switch (drag->type) { + case WM_DRAG_ID: { + ID *id = WM_drag_ID(drag, 0); + bool single = (BLI_listbase_count_at_most(&drag->ids, 2) == 1); + + if (single) { + return id->name + 2; + } + else if (id) { + return BKE_idcode_to_name_plural(GS(id->name)); + } + break; + } + case WM_DRAG_PATH: + case WM_DRAG_NAME: + return drag->path; + } + return ""; } static void drag_rect_minmax(rcti *rect, int x1, int y1, int x2, int y2) { - if (rect->xmin > x1) { - rect->xmin = x1; - } - if (rect->xmax < x2) { - rect->xmax = x2; - } - if (rect->ymin > y1) { - rect->ymin = y1; - } - if (rect->ymax < y2) { - rect->ymax = y2; - } + if (rect->xmin > x1) { + rect->xmin = x1; + } + if (rect->xmax < x2) { + rect->xmax = x2; + } + if (rect->ymin > y1) { + rect->ymin = y1; + } + if (rect->ymax < y2) { + rect->ymax = y2; + } } /* called in wm_draw.c */ /* if rect set, do not draw */ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) { - const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; - wmWindowManager *wm = CTX_wm_manager(C); - wmDrag *drag; - const int winsize_y = WM_window_pixels_y(win); - int cursorx, cursory, x, y; - - cursorx = win->eventstate->x; - cursory = win->eventstate->y; - if (rect) { - rect->xmin = rect->xmax = cursorx; - rect->ymin = rect->ymax = cursory; - } - - /* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */ - GPU_blend(true); - for (drag = wm->drags.first; drag; drag = drag->next) { - const char text_col[] = {255, 255, 255, 255}; - int iconsize = UI_DPI_ICON_SIZE; - int padding = 4 * UI_DPI_FAC; - - /* image or icon */ - if (drag->imb) { - x = cursorx - drag->sx / 2; - y = cursory - drag->sy / 2; - - if (rect) { - drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy); - } - else { - float col[4] = {1.0f, 1.0f, 1.0f, 0.65f}; /* this blends texture */ - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); - immDrawPixelsTexScaled(&state, x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, - drag->imb->rect, drag->scale, drag->scale, 1.0f, 1.0f, col); - } - } - else { - x = cursorx - 2 * padding; - y = cursory - 2 * UI_DPI_FAC; - - if (rect) { - drag_rect_minmax(rect, x, y, x + iconsize, y + iconsize); - } - else { - UI_icon_draw_aspect(x, y, drag->icon, 1.0f / UI_DPI_FAC, 0.8, text_col); - } - } - - /* item name */ - if (drag->imb) { - x = cursorx - drag->sx / 2; - y = cursory - drag->sy / 2 - iconsize; - } - else { - x = cursorx + 10 * UI_DPI_FAC; - y = cursory + 1 * UI_DPI_FAC; - } - - if (rect) { - int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag)); - drag_rect_minmax(rect, x, y, x + w, y + iconsize); - } - else { - UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag), (uchar *)text_col); - } - - /* operator name with roundbox */ - if (drag->opname[0]) { - if (drag->imb) { - x = cursorx - drag->sx / 2; - - if (cursory + drag->sy / 2 + padding + iconsize < winsize_y) { - y = cursory + drag->sy / 2 + padding; - } - else { - y = cursory - drag->sy / 2 - padding - iconsize - padding - iconsize; - } - } - else { - x = cursorx - 2 * padding; - - if (cursory + iconsize + iconsize < winsize_y) { - y = (cursory + iconsize) + padding; - } - else { - y = (cursory - iconsize) - padding; - } - } - - if (rect) { - int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag)); - drag_rect_minmax(rect, x, y, x + w, y + iconsize); - } - else { - wm_drop_operator_draw(drag->opname, x, y); - } - - } - } - GPU_blend(false); + const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; + wmWindowManager *wm = CTX_wm_manager(C); + wmDrag *drag; + const int winsize_y = WM_window_pixels_y(win); + int cursorx, cursory, x, y; + + cursorx = win->eventstate->x; + cursory = win->eventstate->y; + if (rect) { + rect->xmin = rect->xmax = cursorx; + rect->ymin = rect->ymax = cursory; + } + + /* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */ + GPU_blend(true); + for (drag = wm->drags.first; drag; drag = drag->next) { + const char text_col[] = {255, 255, 255, 255}; + int iconsize = UI_DPI_ICON_SIZE; + int padding = 4 * UI_DPI_FAC; + + /* image or icon */ + if (drag->imb) { + x = cursorx - drag->sx / 2; + y = cursory - drag->sy / 2; + + if (rect) { + drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy); + } + else { + float col[4] = {1.0f, 1.0f, 1.0f, 0.65f}; /* this blends texture */ + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTexScaled(&state, + x, + y, + drag->imb->x, + drag->imb->y, + GL_RGBA, + GL_UNSIGNED_BYTE, + GL_NEAREST, + drag->imb->rect, + drag->scale, + drag->scale, + 1.0f, + 1.0f, + col); + } + } + else { + x = cursorx - 2 * padding; + y = cursory - 2 * UI_DPI_FAC; + + if (rect) { + drag_rect_minmax(rect, x, y, x + iconsize, y + iconsize); + } + else { + UI_icon_draw_aspect(x, y, drag->icon, 1.0f / UI_DPI_FAC, 0.8, text_col); + } + } + + /* item name */ + if (drag->imb) { + x = cursorx - drag->sx / 2; + y = cursory - drag->sy / 2 - iconsize; + } + else { + x = cursorx + 10 * UI_DPI_FAC; + y = cursory + 1 * UI_DPI_FAC; + } + + if (rect) { + int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag)); + drag_rect_minmax(rect, x, y, x + w, y + iconsize); + } + else { + UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag), (uchar *)text_col); + } + + /* operator name with roundbox */ + if (drag->opname[0]) { + if (drag->imb) { + x = cursorx - drag->sx / 2; + + if (cursory + drag->sy / 2 + padding + iconsize < winsize_y) { + y = cursory + drag->sy / 2 + padding; + } + else { + y = cursory - drag->sy / 2 - padding - iconsize - padding - iconsize; + } + } + else { + x = cursorx - 2 * padding; + + if (cursory + iconsize + iconsize < winsize_y) { + y = (cursory + iconsize) + padding; + } + else { + y = (cursory - iconsize) - padding; + } + } + + if (rect) { + int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag)); + drag_rect_minmax(rect, x, y, x + w, y + iconsize); + } + else { + wm_drop_operator_draw(drag->opname, x, y); + } + } + } + GPU_blend(false); } diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 08ece1fd5c5..6ecbf4ef5ac 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -77,201 +77,195 @@ # include "BKE_subsurf.h" #endif - /* ******************* paint cursor *************** */ static void wm_paintcursor_draw(bContext *C, ScrArea *sa, ARegion *ar) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - bScreen *screen = WM_window_get_active_screen(win); - wmPaintCursor *pc; - - if (ar->visible && ar == screen->active_region) { - for (pc = wm->paintcursors.first; pc; pc = pc->next) { - - if ((pc->space_type != SPACE_TYPE_ANY) && (sa->spacetype != pc->space_type)) { - continue; - } - - if ((pc->region_type != RGN_TYPE_ANY) && (ar->regiontype != pc->region_type)) { - continue; - } - - if (pc->poll == NULL || pc->poll(C)) { - /* Prevent drawing outside region. */ - glEnable(GL_SCISSOR_TEST); - glScissor(ar->winrct.xmin, - ar->winrct.ymin, - BLI_rcti_size_x(&ar->winrct) + 1, - BLI_rcti_size_y(&ar->winrct) + 1); - - if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) { - int x = 0, y = 0; - wm_get_cursor_position(win, &x, &y); - pc->draw(C, x, y, pc->customdata); - } - else { - pc->draw(C, win->eventstate->x, win->eventstate->y, pc->customdata); - } - - glDisable(GL_SCISSOR_TEST); - } - } - } + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + bScreen *screen = WM_window_get_active_screen(win); + wmPaintCursor *pc; + + if (ar->visible && ar == screen->active_region) { + for (pc = wm->paintcursors.first; pc; pc = pc->next) { + + if ((pc->space_type != SPACE_TYPE_ANY) && (sa->spacetype != pc->space_type)) { + continue; + } + + if ((pc->region_type != RGN_TYPE_ANY) && (ar->regiontype != pc->region_type)) { + continue; + } + + if (pc->poll == NULL || pc->poll(C)) { + /* Prevent drawing outside region. */ + glEnable(GL_SCISSOR_TEST); + glScissor(ar->winrct.xmin, + ar->winrct.ymin, + BLI_rcti_size_x(&ar->winrct) + 1, + BLI_rcti_size_y(&ar->winrct) + 1); + + if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) { + int x = 0, y = 0; + wm_get_cursor_position(win, &x, &y); + pc->draw(C, x, y, pc->customdata); + } + else { + pc->draw(C, win->eventstate->x, win->eventstate->y, pc->customdata); + } + + glDisable(GL_SCISSOR_TEST); + } + } + } } - static bool wm_draw_region_stereo_set(Main *bmain, ScrArea *sa, ARegion *ar, eStereoViews sview) { - /* We could detect better when stereo is actually needed, by inspecting the - * image in the image editor and sequencer. */ - if (!ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_PREVIEW)) { - return false; - } - - switch (sa->spacetype) { - case SPACE_IMAGE: - { - if (ar->regiontype == RGN_TYPE_WINDOW) { - SpaceImage *sima = sa->spacedata.first; - sima->iuser.multiview_eye = sview; - return true; - } - break; - } - case SPACE_VIEW3D: - { - if (ar->regiontype == RGN_TYPE_WINDOW) { - View3D *v3d = sa->spacedata.first; - if (v3d->camera && v3d->camera->type == OB_CAMERA) { - Camera *cam = v3d->camera->data; - CameraBGImage *bgpic = cam->bg_images.first; - v3d->multiview_eye = sview; - if (bgpic) { - bgpic->iuser.multiview_eye = sview; - } - return true; - } - } - break; - } - case SPACE_NODE: - { - if (ar->regiontype == RGN_TYPE_WINDOW) { - SpaceNode *snode = sa->spacedata.first; - if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) { - Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ima->eye = sview; - return true; - } - } - break; - } - case SPACE_SEQ: - { - SpaceSeq *sseq = sa->spacedata.first; - sseq->multiview_eye = sview; - - if (ar->regiontype == RGN_TYPE_PREVIEW) { - return true; - } - else if (ar->regiontype == RGN_TYPE_WINDOW) { - return (sseq->draw_flag & SEQ_DRAW_BACKDROP) != 0; - } - } - } - - return false; + /* We could detect better when stereo is actually needed, by inspecting the + * image in the image editor and sequencer. */ + if (!ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_PREVIEW)) { + return false; + } + + switch (sa->spacetype) { + case SPACE_IMAGE: { + if (ar->regiontype == RGN_TYPE_WINDOW) { + SpaceImage *sima = sa->spacedata.first; + sima->iuser.multiview_eye = sview; + return true; + } + break; + } + case SPACE_VIEW3D: { + if (ar->regiontype == RGN_TYPE_WINDOW) { + View3D *v3d = sa->spacedata.first; + if (v3d->camera && v3d->camera->type == OB_CAMERA) { + Camera *cam = v3d->camera->data; + CameraBGImage *bgpic = cam->bg_images.first; + v3d->multiview_eye = sview; + if (bgpic) { + bgpic->iuser.multiview_eye = sview; + } + return true; + } + } + break; + } + case SPACE_NODE: { + if (ar->regiontype == RGN_TYPE_WINDOW) { + SpaceNode *snode = sa->spacedata.first; + if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) { + Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); + ima->eye = sview; + return true; + } + } + break; + } + case SPACE_SEQ: { + SpaceSeq *sseq = sa->spacedata.first; + sseq->multiview_eye = sview; + + if (ar->regiontype == RGN_TYPE_PREVIEW) { + return true; + } + else if (ar->regiontype == RGN_TYPE_WINDOW) { + return (sseq->draw_flag & SEQ_DRAW_BACKDROP) != 0; + } + } + } + + return false; } /* ********************* drawing ****************** */ static void wm_area_mark_invalid_backbuf(ScrArea *sa) { - if (sa->spacetype == SPACE_VIEW3D) { - ((View3D *)sa->spacedata.first)->flag |= V3D_INVALID_BACKBUF; - } + if (sa->spacetype == SPACE_VIEW3D) { + ((View3D *)sa->spacedata.first)->flag |= V3D_INVALID_BACKBUF; + } } -static void wm_region_test_render_do_draw(const Scene *scene, struct Depsgraph *depsgraph, - ScrArea *sa, ARegion *ar) +static void wm_region_test_render_do_draw(const Scene *scene, + struct Depsgraph *depsgraph, + ScrArea *sa, + ARegion *ar) { - /* tag region for redraw from render engine preview running inside of it */ - if (sa->spacetype == SPACE_VIEW3D && ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - RenderEngine *engine = rv3d->render_engine; - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - - if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) { - View3D *v3d = sa->spacedata.first; - rcti border_rect; - - /* do partial redraw when possible */ - if (ED_view3d_calc_render_border(scene, depsgraph, v3d, ar, &border_rect)) { - ED_region_tag_redraw_partial(ar, &border_rect); - } - else { - ED_region_tag_redraw(ar); - } - - engine->flag &= ~RE_ENGINE_DO_DRAW; - } - else if (viewport && GPU_viewport_do_update(viewport)) { - ED_region_tag_redraw(ar); - } - } + /* tag region for redraw from render engine preview running inside of it */ + if (sa->spacetype == SPACE_VIEW3D && ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + RenderEngine *engine = rv3d->render_engine; + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + + if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) { + View3D *v3d = sa->spacedata.first; + rcti border_rect; + + /* do partial redraw when possible */ + if (ED_view3d_calc_render_border(scene, depsgraph, v3d, ar, &border_rect)) { + ED_region_tag_redraw_partial(ar, &border_rect); + } + else { + ED_region_tag_redraw(ar); + } + + engine->flag &= ~RE_ENGINE_DO_DRAW; + } + else if (viewport && GPU_viewport_do_update(viewport)) { + ED_region_tag_redraw(ar); + } + } } static bool wm_region_use_viewport(ScrArea *sa, ARegion *ar) { - return (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && ar->regiontype == RGN_TYPE_WINDOW); + return (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && ar->regiontype == RGN_TYPE_WINDOW); } /********************** draw all **************************/ /* - reference method, draw all each time */ typedef struct WindowDrawCB { - struct WindowDrawCB *next, *prev; + struct WindowDrawCB *next, *prev; - void(*draw)(const struct wmWindow *, void *); - void *customdata; + void (*draw)(const struct wmWindow *, void *); + void *customdata; } WindowDrawCB; -void *WM_draw_cb_activate( - wmWindow *win, - void(*draw)(const struct wmWindow *, void *), - void *customdata) +void *WM_draw_cb_activate(wmWindow *win, + void (*draw)(const struct wmWindow *, void *), + void *customdata) { - WindowDrawCB *wdc = MEM_callocN(sizeof(*wdc), "WindowDrawCB"); + WindowDrawCB *wdc = MEM_callocN(sizeof(*wdc), "WindowDrawCB"); - BLI_addtail(&win->drawcalls, wdc); - wdc->draw = draw; - wdc->customdata = customdata; + BLI_addtail(&win->drawcalls, wdc); + wdc->draw = draw; + wdc->customdata = customdata; - return wdc; + return wdc; } void WM_draw_cb_exit(wmWindow *win, void *handle) { - for (WindowDrawCB *wdc = win->drawcalls.first; wdc; wdc = wdc->next) { - if (wdc == (WindowDrawCB *)handle) { - BLI_remlink(&win->drawcalls, wdc); - MEM_freeN(wdc); - return; - } - } + for (WindowDrawCB *wdc = win->drawcalls.first; wdc; wdc = wdc->next) { + if (wdc == (WindowDrawCB *)handle) { + BLI_remlink(&win->drawcalls, wdc); + MEM_freeN(wdc); + return; + } + } } static void wm_draw_callbacks(wmWindow *win) { - for (WindowDrawCB *wdc = win->drawcalls.first; wdc; wdc = wdc->next) { - wdc->draw(win, wdc->customdata); - } + for (WindowDrawCB *wdc = win->drawcalls.first; wdc; wdc = wdc->next) { + wdc->draw(win, wdc->customdata); + } } - /************************* Region drawing. ******************************** * * Each region draws into its own framebuffer, which is then blit on the @@ -281,508 +275,521 @@ static void wm_draw_callbacks(wmWindow *win) static void wm_draw_region_buffer_free(ARegion *ar) { - if (ar->draw_buffer) { - for (int view = 0; view < 2; view++) { - if (ar->draw_buffer->offscreen[view]) { - GPU_offscreen_free(ar->draw_buffer->offscreen[view]); - } - if (ar->draw_buffer->viewport[view]) { - GPU_viewport_free(ar->draw_buffer->viewport[view]); - } - } - - MEM_freeN(ar->draw_buffer); - ar->draw_buffer = NULL; - } + if (ar->draw_buffer) { + for (int view = 0; view < 2; view++) { + if (ar->draw_buffer->offscreen[view]) { + GPU_offscreen_free(ar->draw_buffer->offscreen[view]); + } + if (ar->draw_buffer->viewport[view]) { + GPU_viewport_free(ar->draw_buffer->viewport[view]); + } + } + + MEM_freeN(ar->draw_buffer); + ar->draw_buffer = NULL; + } } static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen) { - /* Setup offscreen color texture for drawing. */ - GPUTexture *texture = GPU_offscreen_color_texture(offscreen); + /* Setup offscreen color texture for drawing. */ + GPUTexture *texture = GPU_offscreen_color_texture(offscreen); - /* We don't support multisample textures here. */ - BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D); + /* We don't support multisample textures here. */ + BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); + glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); - /* No mipmaps or filtering. */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - /* GL_TEXTURE_BASE_LEVEL = 0 by default */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + /* No mipmaps or filtering. */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + /* GL_TEXTURE_BASE_LEVEL = 0 by default */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, 0); } static void wm_draw_region_buffer_create(ARegion *ar, bool stereo, bool use_viewport) { - if (ar->draw_buffer) { - if (ar->draw_buffer->stereo != stereo) { - /* Free draw buffer on stereo changes. */ - wm_draw_region_buffer_free(ar); - } - else { - /* Free offscreen buffer on size changes. Viewport auto resizes. */ - GPUOffScreen *offscreen = ar->draw_buffer->offscreen[0]; - if (offscreen && (GPU_offscreen_width(offscreen) != ar->winx || - GPU_offscreen_height(offscreen) != ar->winy)) - { - wm_draw_region_buffer_free(ar); - } - } - } - - if (!ar->draw_buffer) { - if (use_viewport) { - /* Allocate viewport which includes an offscreen buffer with depth - * multisample, etc. */ - ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); - ar->draw_buffer->viewport[0] = GPU_viewport_create(); - ar->draw_buffer->viewport[1] = (stereo) ? GPU_viewport_create() : NULL; - } - else { - /* Allocate offscreen buffer if it does not exist. This one has no - * depth or multisample buffers. 3D view creates own buffers with - * the data it needs. */ - GPUOffScreen *offscreen = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL); - if (!offscreen) { - return; - } - - wm_draw_offscreen_texture_parameters(offscreen); - - GPUOffScreen *offscreen_right = NULL; - if (stereo) { - offscreen_right = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL); - - if (!offscreen_right) { - GPU_offscreen_free(offscreen); - return; - } - - wm_draw_offscreen_texture_parameters(offscreen_right); - } - - ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); - ar->draw_buffer->offscreen[0] = offscreen; - ar->draw_buffer->offscreen[1] = offscreen_right; - } - - ar->draw_buffer->bound_view = -1; - ar->draw_buffer->stereo = stereo; - } + if (ar->draw_buffer) { + if (ar->draw_buffer->stereo != stereo) { + /* Free draw buffer on stereo changes. */ + wm_draw_region_buffer_free(ar); + } + else { + /* Free offscreen buffer on size changes. Viewport auto resizes. */ + GPUOffScreen *offscreen = ar->draw_buffer->offscreen[0]; + if (offscreen && (GPU_offscreen_width(offscreen) != ar->winx || + GPU_offscreen_height(offscreen) != ar->winy)) { + wm_draw_region_buffer_free(ar); + } + } + } + + if (!ar->draw_buffer) { + if (use_viewport) { + /* Allocate viewport which includes an offscreen buffer with depth + * multisample, etc. */ + ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); + ar->draw_buffer->viewport[0] = GPU_viewport_create(); + ar->draw_buffer->viewport[1] = (stereo) ? GPU_viewport_create() : NULL; + } + else { + /* Allocate offscreen buffer if it does not exist. This one has no + * depth or multisample buffers. 3D view creates own buffers with + * the data it needs. */ + GPUOffScreen *offscreen = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL); + if (!offscreen) { + return; + } + + wm_draw_offscreen_texture_parameters(offscreen); + + GPUOffScreen *offscreen_right = NULL; + if (stereo) { + offscreen_right = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL); + + if (!offscreen_right) { + GPU_offscreen_free(offscreen); + return; + } + + wm_draw_offscreen_texture_parameters(offscreen_right); + } + + ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); + ar->draw_buffer->offscreen[0] = offscreen; + ar->draw_buffer->offscreen[1] = offscreen_right; + } + + ar->draw_buffer->bound_view = -1; + ar->draw_buffer->stereo = stereo; + } } static void wm_draw_region_bind(ARegion *ar, int view) { - if (!ar->draw_buffer) { - return; - } - - if (ar->draw_buffer->viewport[view]) { - GPU_viewport_bind(ar->draw_buffer->viewport[view], &ar->winrct); - } - else { - GPU_offscreen_bind(ar->draw_buffer->offscreen[view], false); - - /* For now scissor is expected by region drawing, we could disable it - * and do the enable/disable in the specific cases that setup scissor. */ - glEnable(GL_SCISSOR_TEST); - glScissor(0, 0, ar->winx, ar->winy); - } - - ar->draw_buffer->bound_view = view; + if (!ar->draw_buffer) { + return; + } + + if (ar->draw_buffer->viewport[view]) { + GPU_viewport_bind(ar->draw_buffer->viewport[view], &ar->winrct); + } + else { + GPU_offscreen_bind(ar->draw_buffer->offscreen[view], false); + + /* For now scissor is expected by region drawing, we could disable it + * and do the enable/disable in the specific cases that setup scissor. */ + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, ar->winx, ar->winy); + } + + ar->draw_buffer->bound_view = view; } static void wm_draw_region_unbind(ARegion *ar, int view) { - if (!ar->draw_buffer) { - return; - } - - ar->draw_buffer->bound_view = -1; - - if (ar->draw_buffer->viewport[view]) { - GPU_viewport_unbind(ar->draw_buffer->viewport[view]); - } - else { - glDisable(GL_SCISSOR_TEST); - GPU_offscreen_unbind(ar->draw_buffer->offscreen[view], false); - } + if (!ar->draw_buffer) { + return; + } + + ar->draw_buffer->bound_view = -1; + + if (ar->draw_buffer->viewport[view]) { + GPU_viewport_unbind(ar->draw_buffer->viewport[view]); + } + else { + glDisable(GL_SCISSOR_TEST); + GPU_offscreen_unbind(ar->draw_buffer->offscreen[view], false); + } } static void wm_draw_region_blit(ARegion *ar, int view) { - if (!ar->draw_buffer) { - return; - } - - if (ar->draw_buffer->viewport[view]) { - GPU_viewport_draw_to_screen(ar->draw_buffer->viewport[view], &ar->winrct); - } - else { - GPU_offscreen_draw_to_screen(ar->draw_buffer->offscreen[view], ar->winrct.xmin, ar->winrct.ymin); - } + if (!ar->draw_buffer) { + return; + } + + if (ar->draw_buffer->viewport[view]) { + GPU_viewport_draw_to_screen(ar->draw_buffer->viewport[view], &ar->winrct); + } + else { + GPU_offscreen_draw_to_screen( + ar->draw_buffer->offscreen[view], ar->winrct.xmin, ar->winrct.ymin); + } } GPUTexture *wm_draw_region_texture(ARegion *ar, int view) { - if (!ar->draw_buffer) { - return NULL; - } - - if (ar->draw_buffer->viewport[view]) { - return GPU_viewport_color_texture(ar->draw_buffer->viewport[view]); - } - else { - return GPU_offscreen_color_texture(ar->draw_buffer->offscreen[view]); - } + if (!ar->draw_buffer) { + return NULL; + } + + if (ar->draw_buffer->viewport[view]) { + return GPU_viewport_color_texture(ar->draw_buffer->viewport[view]); + } + else { + return GPU_offscreen_color_texture(ar->draw_buffer->offscreen[view]); + } } void wm_draw_region_blend(ARegion *ar, int view, bool blend) { - if (!ar->draw_buffer) { - return; - } - - /* Alpha is always 1, except when blend timer is running. */ - float alpha = ED_region_blend_alpha(ar); - if (alpha <= 0.0f) { - return; - } - - if (!blend) { - alpha = 1.0f; - } - - /* setup actual texture */ - GPUTexture *texture = wm_draw_region_texture(ar, view); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); - - /* wmOrtho for the screen has this same offset */ - const float halfx = GLA_PIXEL_OFS / (BLI_rcti_size_x(&ar->winrct) + 1); - const float halfy = GLA_PIXEL_OFS / (BLI_rcti_size_y(&ar->winrct) + 1); - - if (blend) { - /* GL_ONE because regions drawn offscreen have premultiplied alpha. */ - GPU_blend(true); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); - GPU_shader_bind(shader); - - rcti rect_geo = ar->winrct; - rect_geo.xmax += 1; - rect_geo.ymax += 1; - - rctf rect_tex; - rect_tex.xmin = halfx; - rect_tex.ymin = halfy; - rect_tex.xmax = 1.0f + halfx; - rect_tex.ymax = 1.0f + halfy; - - float alpha_easing = 1.0f - alpha; - alpha_easing = 1.0f - alpha_easing * alpha_easing; - - /* Slide vertical panels */ - float ofs_x = BLI_rcti_size_x(&ar->winrct) * (1.0f - alpha_easing); - if (ar->alignment == RGN_ALIGN_RIGHT) { - rect_geo.xmin += ofs_x; - rect_tex.xmax *= alpha_easing; - alpha = 1.0f; - } - else if (ar->alignment == RGN_ALIGN_LEFT) { - rect_geo.xmax -= ofs_x; - rect_tex.xmin += 1.0f - alpha_easing; - alpha = 1.0f; - } - - glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), rect_tex.xmin, rect_tex.ymin, rect_tex.xmax, rect_tex.ymax); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), rect_geo.xmin, rect_geo.ymin, rect_geo.xmax, rect_geo.ymax); - glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha); - - GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4); - - glBindTexture(GL_TEXTURE_2D, 0); - - if (blend) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - GPU_blend(false); - } + if (!ar->draw_buffer) { + return; + } + + /* Alpha is always 1, except when blend timer is running. */ + float alpha = ED_region_blend_alpha(ar); + if (alpha <= 0.0f) { + return; + } + + if (!blend) { + alpha = 1.0f; + } + + /* setup actual texture */ + GPUTexture *texture = wm_draw_region_texture(ar, view); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); + + /* wmOrtho for the screen has this same offset */ + const float halfx = GLA_PIXEL_OFS / (BLI_rcti_size_x(&ar->winrct) + 1); + const float halfy = GLA_PIXEL_OFS / (BLI_rcti_size_y(&ar->winrct) + 1); + + if (blend) { + /* GL_ONE because regions drawn offscreen have premultiplied alpha. */ + GPU_blend(true); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); + GPU_shader_bind(shader); + + rcti rect_geo = ar->winrct; + rect_geo.xmax += 1; + rect_geo.ymax += 1; + + rctf rect_tex; + rect_tex.xmin = halfx; + rect_tex.ymin = halfy; + rect_tex.xmax = 1.0f + halfx; + rect_tex.ymax = 1.0f + halfy; + + float alpha_easing = 1.0f - alpha; + alpha_easing = 1.0f - alpha_easing * alpha_easing; + + /* Slide vertical panels */ + float ofs_x = BLI_rcti_size_x(&ar->winrct) * (1.0f - alpha_easing); + if (ar->alignment == RGN_ALIGN_RIGHT) { + rect_geo.xmin += ofs_x; + rect_tex.xmax *= alpha_easing; + alpha = 1.0f; + } + else if (ar->alignment == RGN_ALIGN_LEFT) { + rect_geo.xmax -= ofs_x; + rect_tex.xmin += 1.0f - alpha_easing; + alpha = 1.0f; + } + + glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0); + glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), + rect_tex.xmin, + rect_tex.ymin, + rect_tex.xmax, + rect_tex.ymax); + glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), + rect_geo.xmin, + rect_geo.ymin, + rect_geo.xmax, + rect_geo.ymax); + glUniform4f( + GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha); + + GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4); + + glBindTexture(GL_TEXTURE_2D, 0); + + if (blend) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GPU_blend(false); + } } GPUViewport *WM_draw_region_get_viewport(ARegion *ar, int view) { - if (!ar->draw_buffer) { - return NULL; - } + if (!ar->draw_buffer) { + return NULL; + } - return ar->draw_buffer->viewport[view]; + return ar->draw_buffer->viewport[view]; } GPUViewport *WM_draw_region_get_bound_viewport(ARegion *ar) { - if (!ar->draw_buffer || ar->draw_buffer->bound_view == -1) { - return NULL; - } + if (!ar->draw_buffer || ar->draw_buffer->bound_view == -1) { + return NULL; + } - int view = ar->draw_buffer->bound_view; - return ar->draw_buffer->viewport[view]; + int view = ar->draw_buffer->bound_view; + return ar->draw_buffer->viewport[view]; } static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); - bScreen *screen = WM_window_get_active_screen(win); - - /* Draw screen areas into own frame buffer. */ - ED_screen_areas_iter(win, screen, sa) { - CTX_wm_area_set(C, sa); - - /* Compute UI layouts for dynamically size regions. */ - for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar->do_draw && ar->type && ar->type->layout) { - CTX_wm_region_set(C, ar); - ED_region_do_layout(C, ar); - CTX_wm_region_set(C, NULL); - } - } - - ED_area_update_region_sizes(wm, win, sa); - - if (sa->flag & AREA_FLAG_ACTIVE_TOOL_UPDATE) { - if ((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) { - WM_toolsystem_update_from_context(C, CTX_wm_workspace(C), CTX_data_view_layer(C), sa); - } - sa->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE; - } - - /* Then do actual drawing of regions. */ - for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar->do_draw) { - CTX_wm_region_set(C, ar); - bool use_viewport = wm_region_use_viewport(sa, ar); - - if (stereo && wm_draw_region_stereo_set(bmain, sa, ar, STEREO_LEFT_ID)) { - wm_draw_region_buffer_create(ar, true, use_viewport); - - for (int view = 0; view < 2; view++) { - eStereoViews sview; - if (view == 0) { - sview = STEREO_LEFT_ID; - } - else { - sview = STEREO_RIGHT_ID; - wm_draw_region_stereo_set(bmain, sa, ar, sview); - } - - wm_draw_region_bind(ar, view); - ED_region_do_draw(C, ar); - wm_draw_region_unbind(ar, view); - } - } - else { - wm_draw_region_buffer_create(ar, false, use_viewport); - wm_draw_region_bind(ar, 0); - ED_region_do_draw(C, ar); - wm_draw_region_unbind(ar, 0); - } - - ar->do_draw = false; - CTX_wm_region_set(C, NULL); - } - } - - wm_area_mark_invalid_backbuf(sa); - CTX_wm_area_set(C, NULL); - } - - /* Draw menus into their own framebuffer. */ - for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { - if (ar->visible) { - CTX_wm_menu_set(C, ar); - - if (ar->type && ar->type->layout) { - /* UI code reads the OpenGL state, but we have to refresh - * the UI layout beforehand in case the menu size changes. */ - wmViewport(&ar->winrct); - ar->type->layout(C, ar); - } - - wm_draw_region_buffer_create(ar, false, false); - wm_draw_region_bind(ar, 0); - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); - ED_region_do_draw(C, ar); - wm_draw_region_unbind(ar, 0); - - ar->do_draw = false; - CTX_wm_menu_set(C, NULL); - } - } + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = CTX_wm_manager(C); + bScreen *screen = WM_window_get_active_screen(win); + + /* Draw screen areas into own frame buffer. */ + ED_screen_areas_iter(win, screen, sa) + { + CTX_wm_area_set(C, sa); + + /* Compute UI layouts for dynamically size regions. */ + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->visible && ar->do_draw && ar->type && ar->type->layout) { + CTX_wm_region_set(C, ar); + ED_region_do_layout(C, ar); + CTX_wm_region_set(C, NULL); + } + } + + ED_area_update_region_sizes(wm, win, sa); + + if (sa->flag & AREA_FLAG_ACTIVE_TOOL_UPDATE) { + if ((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) { + WM_toolsystem_update_from_context(C, CTX_wm_workspace(C), CTX_data_view_layer(C), sa); + } + sa->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE; + } + + /* Then do actual drawing of regions. */ + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->visible && ar->do_draw) { + CTX_wm_region_set(C, ar); + bool use_viewport = wm_region_use_viewport(sa, ar); + + if (stereo && wm_draw_region_stereo_set(bmain, sa, ar, STEREO_LEFT_ID)) { + wm_draw_region_buffer_create(ar, true, use_viewport); + + for (int view = 0; view < 2; view++) { + eStereoViews sview; + if (view == 0) { + sview = STEREO_LEFT_ID; + } + else { + sview = STEREO_RIGHT_ID; + wm_draw_region_stereo_set(bmain, sa, ar, sview); + } + + wm_draw_region_bind(ar, view); + ED_region_do_draw(C, ar); + wm_draw_region_unbind(ar, view); + } + } + else { + wm_draw_region_buffer_create(ar, false, use_viewport); + wm_draw_region_bind(ar, 0); + ED_region_do_draw(C, ar); + wm_draw_region_unbind(ar, 0); + } + + ar->do_draw = false; + CTX_wm_region_set(C, NULL); + } + } + + wm_area_mark_invalid_backbuf(sa); + CTX_wm_area_set(C, NULL); + } + + /* Draw menus into their own framebuffer. */ + for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { + if (ar->visible) { + CTX_wm_menu_set(C, ar); + + if (ar->type && ar->type->layout) { + /* UI code reads the OpenGL state, but we have to refresh + * the UI layout beforehand in case the menu size changes. */ + wmViewport(&ar->winrct); + ar->type->layout(C, ar); + } + + wm_draw_region_buffer_create(ar, false, false); + wm_draw_region_bind(ar, 0); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + ED_region_do_draw(C, ar); + wm_draw_region_unbind(ar, 0); + + ar->do_draw = false; + CTX_wm_menu_set(C, NULL); + } + } } static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) { - wmWindowManager *wm = CTX_wm_manager(C); - bScreen *screen = WM_window_get_active_screen(win); + wmWindowManager *wm = CTX_wm_manager(C); + bScreen *screen = WM_window_get_active_screen(win); - /* Draw into the window framebuffer, in full window coordinates. */ - wmWindowViewport(win); + /* Draw into the window framebuffer, in full window coordinates. */ + wmWindowViewport(win); - /* We draw on all pixels of the windows so we don't need to clear them before. - * Actually this is only a problem when resizing the window. - * If it becomes a problem we should clear only when window size changes. */ + /* We draw on all pixels of the windows so we don't need to clear them before. + * Actually this is only a problem when resizing the window. + * If it becomes a problem we should clear only when window size changes. */ #if 0 - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); #endif - /* Blit non-overlapping area regions. */ - ED_screen_areas_iter(win, screen, sa) { - for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar->overlap == false) { - if (view == -1 && ar->draw_buffer && ar->draw_buffer->stereo) { - /* Stereo drawing from textures. */ - if (win->stereo3d_format->display_mode == S3D_DISPLAY_ANAGLYPH) { - wm_stereo3d_draw_anaglyph(win, ar); - } - else { - wm_stereo3d_draw_interlace(win, ar); - } - } - else { - /* Blit from offscreen buffer. */ - wm_draw_region_blit(ar, 0); - } - } - } - } - - /* Draw paint cursors. */ - if (wm->paintcursors.first) { - ED_screen_areas_iter(win, screen, sa) { - for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar == screen->active_region) { - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); - - /* make region ready for draw, scissor, pixelspace */ - wm_paintcursor_draw(C, sa, ar); - - CTX_wm_region_set(C, NULL); - CTX_wm_area_set(C, NULL); - } - } - } - - wmWindowViewport(win); - } - - /* Blend in overlapping area regions */ - ED_screen_areas_iter(win, screen, sa) { - for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar->overlap) { - wm_draw_region_blend(ar, 0, true); - } - } - } - - /* After area regions so we can do area 'overlay' drawing. */ - ED_screen_draw_edges(win); - wm_draw_callbacks(win); - - /* Blend in floating regions (menus). */ - for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { - if (ar->visible) { - wm_draw_region_blend(ar, 0, true); - } - } - - /* always draw, not only when screen tagged */ - if (win->gesture.first) { - wm_gesture_draw(win); - } - - /* needs pixel coords in screen */ - if (wm->drags.first) { - wm_drags_draw(C, win, NULL); - } + /* Blit non-overlapping area regions. */ + ED_screen_areas_iter(win, screen, sa) + { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->visible && ar->overlap == false) { + if (view == -1 && ar->draw_buffer && ar->draw_buffer->stereo) { + /* Stereo drawing from textures. */ + if (win->stereo3d_format->display_mode == S3D_DISPLAY_ANAGLYPH) { + wm_stereo3d_draw_anaglyph(win, ar); + } + else { + wm_stereo3d_draw_interlace(win, ar); + } + } + else { + /* Blit from offscreen buffer. */ + wm_draw_region_blit(ar, 0); + } + } + } + } + + /* Draw paint cursors. */ + if (wm->paintcursors.first) { + ED_screen_areas_iter(win, screen, sa) + { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->visible && ar == screen->active_region) { + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + + /* make region ready for draw, scissor, pixelspace */ + wm_paintcursor_draw(C, sa, ar); + + CTX_wm_region_set(C, NULL); + CTX_wm_area_set(C, NULL); + } + } + } + + wmWindowViewport(win); + } + + /* Blend in overlapping area regions */ + ED_screen_areas_iter(win, screen, sa) + { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->visible && ar->overlap) { + wm_draw_region_blend(ar, 0, true); + } + } + } + + /* After area regions so we can do area 'overlay' drawing. */ + ED_screen_draw_edges(win); + wm_draw_callbacks(win); + + /* Blend in floating regions (menus). */ + for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { + if (ar->visible) { + wm_draw_region_blend(ar, 0, true); + } + } + + /* always draw, not only when screen tagged */ + if (win->gesture.first) { + wm_gesture_draw(win); + } + + /* needs pixel coords in screen */ + if (wm->drags.first) { + wm_drags_draw(C, win, NULL); + } } static void wm_draw_window(bContext *C, wmWindow *win) { - bScreen *screen = WM_window_get_active_screen(win); - bool stereo = WM_stereo3d_enabled(win, false); - - /* Draw area regions into their own framebuffer. This way we can redraw - * the areas that need it, and blit the rest from existing framebuffers. */ - wm_draw_window_offscreen(C, win, stereo); - - /* Now we draw into the window framebuffer, in full window coordinates. */ - if (!stereo) { - /* Regular mono drawing. */ - wm_draw_window_onscreen(C, win, -1); - } - else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { - /* For pageflip we simply draw to both back buffers. */ - glDrawBuffer(GL_BACK_LEFT); - wm_draw_window_onscreen(C, win, 0); - glDrawBuffer(GL_BACK_RIGHT); - wm_draw_window_onscreen(C, win, 1); - glDrawBuffer(GL_BACK); - } - else if (ELEM(win->stereo3d_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) { - /* For anaglyph and interlace, we draw individual regions with - * stereo framebuffers using different shaders. */ - wm_draw_window_onscreen(C, win, -1); - } - else { - /* For side-by-side and top-bottom, we need to render each view to an - * an offscreen texture and then draw it. This used to happen for all - * stereo methods, but it's less efficient than drawing directly. */ - const int width = WM_window_pixels_x(win); - const int height = WM_window_pixels_y(win); - GPUOffScreen *offscreen = GPU_offscreen_create(width, height, 0, false, false, NULL); - - if (offscreen) { - GPUTexture *texture = GPU_offscreen_color_texture(offscreen); - wm_draw_offscreen_texture_parameters(offscreen); - - for (int view = 0; view < 2; view++) { - /* Draw view into offscreen buffer. */ - GPU_offscreen_bind(offscreen, false); - wm_draw_window_onscreen(C, win, view); - GPU_offscreen_unbind(offscreen, false); - - /* Draw offscreen buffer to screen. */ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); - - if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) { - wm_stereo3d_draw_sidebyside(win, view); - } - else { - wm_stereo3d_draw_topbottom(win, view); - } - - glBindTexture(GL_TEXTURE_2D, 0); - } - - GPU_offscreen_free(offscreen); - } - else { - /* Still draw something in case of allocation failure. */ - wm_draw_window_onscreen(C, win, 0); - } - } - - screen->do_draw = false; + bScreen *screen = WM_window_get_active_screen(win); + bool stereo = WM_stereo3d_enabled(win, false); + + /* Draw area regions into their own framebuffer. This way we can redraw + * the areas that need it, and blit the rest from existing framebuffers. */ + wm_draw_window_offscreen(C, win, stereo); + + /* Now we draw into the window framebuffer, in full window coordinates. */ + if (!stereo) { + /* Regular mono drawing. */ + wm_draw_window_onscreen(C, win, -1); + } + else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + /* For pageflip we simply draw to both back buffers. */ + glDrawBuffer(GL_BACK_LEFT); + wm_draw_window_onscreen(C, win, 0); + glDrawBuffer(GL_BACK_RIGHT); + wm_draw_window_onscreen(C, win, 1); + glDrawBuffer(GL_BACK); + } + else if (ELEM(win->stereo3d_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) { + /* For anaglyph and interlace, we draw individual regions with + * stereo framebuffers using different shaders. */ + wm_draw_window_onscreen(C, win, -1); + } + else { + /* For side-by-side and top-bottom, we need to render each view to an + * an offscreen texture and then draw it. This used to happen for all + * stereo methods, but it's less efficient than drawing directly. */ + const int width = WM_window_pixels_x(win); + const int height = WM_window_pixels_y(win); + GPUOffScreen *offscreen = GPU_offscreen_create(width, height, 0, false, false, NULL); + + if (offscreen) { + GPUTexture *texture = GPU_offscreen_color_texture(offscreen); + wm_draw_offscreen_texture_parameters(offscreen); + + for (int view = 0; view < 2; view++) { + /* Draw view into offscreen buffer. */ + GPU_offscreen_bind(offscreen, false); + wm_draw_window_onscreen(C, win, view); + GPU_offscreen_unbind(offscreen, false); + + /* Draw offscreen buffer to screen. */ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); + + if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) { + wm_stereo3d_draw_sidebyside(win, view); + } + else { + wm_stereo3d_draw_topbottom(win, view); + } + + glBindTexture(GL_TEXTURE_2D, 0); + } + + GPU_offscreen_free(offscreen); + } + else { + /* Still draw something in case of allocation failure. */ + wm_draw_window_onscreen(C, win, 0); + } + } + + screen->do_draw = false; } /****************** main update call **********************/ @@ -790,134 +797,135 @@ static void wm_draw_window(bContext *C, wmWindow *win) /* quick test to prevent changing window drawable */ static bool wm_draw_update_test_window(wmWindow *win) { - Scene *scene = WM_window_get_active_scene(win); - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); - bScreen *screen = WM_window_get_active_screen(win); - ARegion *ar; - bool do_draw = false; - - for (ar = screen->regionbase.first; ar; ar = ar->next) { - if (ar->do_draw_overlay) { - screen->do_draw_paintcursor = true; - ar->do_draw_overlay = false; - } - if (ar->visible && ar->do_draw) { - do_draw = true; - } - } - - ED_screen_areas_iter(win, screen, sa) { - for (ar = sa->regionbase.first; ar; ar = ar->next) { - wm_region_test_render_do_draw(scene, depsgraph, sa, ar); - - if (ar->visible && ar->do_draw) { - do_draw = true; - } - } - } - - if (do_draw) { - return true; - } - - if (screen->do_refresh) { - return true; - } - if (screen->do_draw) { - return true; - } - if (screen->do_draw_gesture) { - return true; - } - if (screen->do_draw_paintcursor) { - return true; - } - if (screen->do_draw_drag) { - return true; - } - - return false; + Scene *scene = WM_window_get_active_scene(win); + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); + bScreen *screen = WM_window_get_active_screen(win); + ARegion *ar; + bool do_draw = false; + + for (ar = screen->regionbase.first; ar; ar = ar->next) { + if (ar->do_draw_overlay) { + screen->do_draw_paintcursor = true; + ar->do_draw_overlay = false; + } + if (ar->visible && ar->do_draw) { + do_draw = true; + } + } + + ED_screen_areas_iter(win, screen, sa) + { + for (ar = sa->regionbase.first; ar; ar = ar->next) { + wm_region_test_render_do_draw(scene, depsgraph, sa, ar); + + if (ar->visible && ar->do_draw) { + do_draw = true; + } + } + } + + if (do_draw) { + return true; + } + + if (screen->do_refresh) { + return true; + } + if (screen->do_draw) { + return true; + } + if (screen->do_draw_gesture) { + return true; + } + if (screen->do_draw_paintcursor) { + return true; + } + if (screen->do_draw_drag) { + return true; + } + + return false; } void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *UNUSED(ar)) { - if (win) { - bScreen *screen = WM_window_get_active_screen(win); - screen->do_draw_paintcursor = true; - } + if (win) { + bScreen *screen = WM_window_get_active_screen(win); + screen->do_draw_paintcursor = true; + } } void wm_draw_update(bContext *C) { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win; + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win; #ifdef WITH_OPENSUBDIV - BKE_subsurf_free_unused_buffers(); + BKE_subsurf_free_unused_buffers(); #endif - GPU_free_unused_buffers(bmain); + GPU_free_unused_buffers(bmain); - for (win = wm->windows.first; win; win = win->next) { + for (win = wm->windows.first; win; win = win->next) { #ifdef WIN32 - GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin); - - if (state == GHOST_kWindowStateMinimized) { - /* do not update minimized windows, gives issues on Intel (see T33223) - * and AMD (see T50856). it seems logical to skip update for invisible - * window anyway. - */ - continue; - } + GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin); + + if (state == GHOST_kWindowStateMinimized) { + /* do not update minimized windows, gives issues on Intel (see T33223) + * and AMD (see T50856). it seems logical to skip update for invisible + * window anyway. + */ + continue; + } #endif - if (wm_draw_update_test_window(win)) { - bScreen *screen = WM_window_get_active_screen(win); + if (wm_draw_update_test_window(win)) { + bScreen *screen = WM_window_get_active_screen(win); - CTX_wm_window_set(C, win); + CTX_wm_window_set(C, win); - /* sets context window+screen */ - wm_window_make_drawable(wm, win); + /* sets context window+screen */ + wm_window_make_drawable(wm, win); - /* notifiers for screen redraw */ - ED_screen_ensure_updated(wm, win, screen); + /* notifiers for screen redraw */ + ED_screen_ensure_updated(wm, win, screen); - wm_draw_window(C, win); + wm_draw_window(C, win); - screen->do_draw_gesture = false; - screen->do_draw_paintcursor = false; - screen->do_draw_drag = false; + screen->do_draw_gesture = false; + screen->do_draw_paintcursor = false; + screen->do_draw_drag = false; - wm_window_swap_buffers(win); + wm_window_swap_buffers(win); - CTX_wm_window_set(C, NULL); - } - } + CTX_wm_window_set(C, NULL); + } + } } void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(ar)) { - bScreen *screen = WM_window_get_active_screen(win); - screen->do_draw = true; + bScreen *screen = WM_window_get_active_screen(win); + screen->do_draw = true; } void WM_draw_region_free(ARegion *ar) { - wm_draw_region_buffer_free(ar); - ar->visible = 0; + wm_draw_region_buffer_free(ar); + ar->visible = 0; } void WM_redraw_windows(bContext *C) { - wmWindow *win_prev = CTX_wm_window(C); - ScrArea *area_prev = CTX_wm_area(C); - ARegion *ar_prev = CTX_wm_region(C); + wmWindow *win_prev = CTX_wm_window(C); + ScrArea *area_prev = CTX_wm_area(C); + ARegion *ar_prev = CTX_wm_region(C); - wm_draw_update(C); + wm_draw_update(C); - CTX_wm_window_set(C, win_prev); - CTX_wm_area_set(C, area_prev); - CTX_wm_region_set(C, ar_prev); + CTX_wm_window_set(C, win_prev); + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, ar_prev); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 5d22eb79601..c31f78339a8 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -93,153 +93,160 @@ static void wm_notifier_clear(wmNotifier *note); static void update_tablet_data(wmWindow *win, wmEvent *event); -static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports, - const short context, const bool poll_only, wmEvent *event); +static int wm_operator_call_internal(bContext *C, + wmOperatorType *ot, + PointerRNA *properties, + ReportList *reports, + const short context, + const bool poll_only, + wmEvent *event); /* ************ event management ************** */ -wmEvent *wm_event_add_ex(wmWindow *win, const wmEvent *event_to_add, const wmEvent *event_to_add_after) +wmEvent *wm_event_add_ex(wmWindow *win, + const wmEvent *event_to_add, + const wmEvent *event_to_add_after) { - wmEvent *event = MEM_mallocN(sizeof(wmEvent), "wmEvent"); - - *event = *event_to_add; - - update_tablet_data(win, event); - - if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - /* We could have a preference to support relative tablet motion (we can't detect that). */ - event->is_motion_absolute = ( - (event->tablet_data != NULL) && - (event->tablet_data->Active != GHOST_kTabletModeNone)); - } - - if (event_to_add_after == NULL) { - BLI_addtail(&win->queue, event); - } - else { - /* note, strictly speaking this breaks const-correctness, however we're only changing 'next' member */ - BLI_insertlinkafter(&win->queue, (void *)event_to_add_after, event); - } - return event; + wmEvent *event = MEM_mallocN(sizeof(wmEvent), "wmEvent"); + + *event = *event_to_add; + + update_tablet_data(win, event); + + if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + /* We could have a preference to support relative tablet motion (we can't detect that). */ + event->is_motion_absolute = ((event->tablet_data != NULL) && + (event->tablet_data->Active != GHOST_kTabletModeNone)); + } + + if (event_to_add_after == NULL) { + BLI_addtail(&win->queue, event); + } + else { + /* note, strictly speaking this breaks const-correctness, however we're only changing 'next' member */ + BLI_insertlinkafter(&win->queue, (void *)event_to_add_after, event); + } + return event; } wmEvent *wm_event_add(wmWindow *win, const wmEvent *event_to_add) { - return wm_event_add_ex(win, event_to_add, NULL); + return wm_event_add_ex(win, event_to_add, NULL); } wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add) { - if ((G.f & G_FLAG_EVENT_SIMULATE) == 0) { - BLI_assert(0); - return NULL; - } - wmEvent *event = wm_event_add(win, event_to_add); - win->eventstate->x = event->x; - win->eventstate->y = event->y; - return event; + if ((G.f & G_FLAG_EVENT_SIMULATE) == 0) { + BLI_assert(0); + return NULL; + } + wmEvent *event = wm_event_add(win, event_to_add); + win->eventstate->x = event->x; + win->eventstate->y = event->y; + return event; } void wm_event_free(wmEvent *event) { - if (event->customdata) { - if (event->customdatafree) { - /* note: pointer to listbase struct elsewhere */ - if (event->custom == EVT_DATA_DRAGDROP) { - ListBase *lb = event->customdata; - WM_drag_free_list(lb); - } - else { - MEM_freeN(event->customdata); - } - } - } - - if (event->tablet_data) { - MEM_freeN((void *)event->tablet_data); - } - - MEM_freeN(event); + if (event->customdata) { + if (event->customdatafree) { + /* note: pointer to listbase struct elsewhere */ + if (event->custom == EVT_DATA_DRAGDROP) { + ListBase *lb = event->customdata; + WM_drag_free_list(lb); + } + else { + MEM_freeN(event->customdata); + } + } + } + + if (event->tablet_data) { + MEM_freeN((void *)event->tablet_data); + } + + MEM_freeN(event); } void wm_event_free_all(wmWindow *win) { - wmEvent *event; + wmEvent *event; - while ((event = BLI_pophead(&win->queue))) { - wm_event_free(event); - } + while ((event = BLI_pophead(&win->queue))) { + wm_event_free(event); + } } void wm_event_init_from_window(wmWindow *win, wmEvent *event) { - /* make sure we don't copy any owned pointers */ - BLI_assert(win->eventstate->tablet_data == NULL); + /* make sure we don't copy any owned pointers */ + BLI_assert(win->eventstate->tablet_data == NULL); - *event = *(win->eventstate); + *event = *(win->eventstate); } /* ********************* notifiers, listeners *************** */ static bool wm_test_duplicate_notifier(wmWindowManager *wm, unsigned int type, void *reference) { - wmNotifier *note; + wmNotifier *note; - for (note = wm->queue.first; note; note = note->next) { - if ((note->category | note->data | note->subtype | note->action) == type && note->reference == reference) { - return 1; - } - } + for (note = wm->queue.first; note; note = note->next) { + if ((note->category | note->data | note->subtype | note->action) == type && + note->reference == reference) { + return 1; + } + } - return 0; + return 0; } /* XXX: in future, which notifiers to send to other windows? */ void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference) { - wmWindowManager *wm = CTX_wm_manager(C); - wmNotifier *note; + wmWindowManager *wm = CTX_wm_manager(C); + wmNotifier *note; - if (wm_test_duplicate_notifier(wm, type, reference)) { - return; - } + if (wm_test_duplicate_notifier(wm, type, reference)) { + return; + } - note = MEM_callocN(sizeof(wmNotifier), "notifier"); + note = MEM_callocN(sizeof(wmNotifier), "notifier"); - note->wm = wm; - BLI_addtail(¬e->wm->queue, note); + note->wm = wm; + BLI_addtail(¬e->wm->queue, note); - note->window = CTX_wm_window(C); + note->window = CTX_wm_window(C); - note->category = type & NOTE_CATEGORY; - note->data = type & NOTE_DATA; - note->subtype = type & NOTE_SUBTYPE; - note->action = type & NOTE_ACTION; + note->category = type & NOTE_CATEGORY; + note->data = type & NOTE_DATA; + note->subtype = type & NOTE_SUBTYPE; + note->action = type & NOTE_ACTION; - note->reference = reference; + note->reference = reference; } void WM_main_add_notifier(unsigned int type, void *reference) { - Main *bmain = G_MAIN; - wmWindowManager *wm = bmain->wm.first; - wmNotifier *note; + Main *bmain = G_MAIN; + wmWindowManager *wm = bmain->wm.first; + wmNotifier *note; - if (!wm || wm_test_duplicate_notifier(wm, type, reference)) { - return; - } + if (!wm || wm_test_duplicate_notifier(wm, type, reference)) { + return; + } - note = MEM_callocN(sizeof(wmNotifier), "notifier"); + note = MEM_callocN(sizeof(wmNotifier), "notifier"); - note->wm = wm; - BLI_addtail(¬e->wm->queue, note); + note->wm = wm; + BLI_addtail(¬e->wm->queue, note); - note->category = type & NOTE_CATEGORY; - note->data = type & NOTE_DATA; - note->subtype = type & NOTE_SUBTYPE; - note->action = type & NOTE_ACTION; + note->category = type & NOTE_CATEGORY; + note->data = type & NOTE_DATA; + note->subtype = type & NOTE_SUBTYPE; + note->action = type & NOTE_ACTION; - note->reference = reference; + note->reference = reference; } /** @@ -247,104 +254,103 @@ void WM_main_add_notifier(unsigned int type, void *reference) */ void WM_main_remove_notifier_reference(const void *reference) { - Main *bmain = G_MAIN; - wmWindowManager *wm = bmain->wm.first; + Main *bmain = G_MAIN; + wmWindowManager *wm = bmain->wm.first; - if (wm) { - wmNotifier *note, *note_next; + if (wm) { + wmNotifier *note, *note_next; - for (note = wm->queue.first; note; note = note_next) { - note_next = note->next; + for (note = wm->queue.first; note; note = note_next) { + note_next = note->next; - if (note->reference == reference) { - /* don't remove because this causes problems for #wm_event_do_notifiers - * which may be looping on the data (deleting screens) */ - wm_notifier_clear(note); - } - } + if (note->reference == reference) { + /* don't remove because this causes problems for #wm_event_do_notifiers + * which may be looping on the data (deleting screens) */ + wm_notifier_clear(note); + } + } - /* Remap instead. */ + /* Remap instead. */ #if 0 - if (wm->message_bus) { - WM_msg_id_remove(wm->message_bus, reference); - } + if (wm->message_bus) { + WM_msg_id_remove(wm->message_bus, reference); + } #endif - - } + } } void WM_main_remap_editor_id_reference(ID *old_id, ID *new_id) { - Main *bmain = G_MAIN; - bScreen *sc; - - for (sc = bmain->screens.first; sc; sc = sc->id.next) { - ScrArea *sa; - - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - - for (sl = sa->spacedata.first; sl; sl = sl->next) { - ED_spacedata_id_remap(sa, sl, old_id, new_id); - } - } - } - - wmWindowManager *wm = bmain->wm.first; - if (wm && wm->message_bus) { - struct wmMsgBus *mbus = wm->message_bus; - if (new_id != NULL) { - WM_msg_id_update(mbus, old_id, new_id); - } - else { - WM_msg_id_remove(mbus, old_id); - } - } + Main *bmain = G_MAIN; + bScreen *sc; + + for (sc = bmain->screens.first; sc; sc = sc->id.next) { + ScrArea *sa; + + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + ED_spacedata_id_remap(sa, sl, old_id, new_id); + } + } + } + + wmWindowManager *wm = bmain->wm.first; + if (wm && wm->message_bus) { + struct wmMsgBus *mbus = wm->message_bus; + if (new_id != NULL) { + WM_msg_id_update(mbus, old_id, new_id); + } + else { + WM_msg_id_remove(mbus, old_id); + } + } } static void wm_notifier_clear(wmNotifier *note) { - /* NULL the entire notifier, only leaving (next, prev) members intact */ - memset(((char *)note) + sizeof(Link), 0, sizeof(*note) - sizeof(Link)); + /* NULL the entire notifier, only leaving (next, prev) members intact */ + memset(((char *)note) + sizeof(Link), 0, sizeof(*note) - sizeof(Link)); } void wm_event_do_depsgraph(bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - /* The whole idea of locked interface is to prevent viewport and whatever - * thread to modify the same data. Because of this, we can not perform - * dependency graph update. - */ - if (wm->is_interface_locked) { - return; - } - /* Combine datamasks so 1 win doesn't disable UV's in another [#26448]. */ - CustomData_MeshMasks win_combine_v3d_datamask = {0}; - for (wmWindow *win = wm->windows.first; win; win = win->next) { - const Scene *scene = WM_window_get_active_scene(win); - const bScreen *screen = WM_window_get_active_screen(win); - - ED_view3d_screen_datamask(C, scene, screen, &win_combine_v3d_datamask); - } - /* Update all the dependency graphs of visible view layers. */ - for (wmWindow *win = wm->windows.first; win; win = win->next) { - Scene *scene = WM_window_get_active_scene(win); - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Main *bmain = CTX_data_main(C); - /* Copied to set's in scene_update_tagged_recursive() */ - scene->customdata_mask = win_combine_v3d_datamask; - /* XXX, hack so operators can enforce datamasks [#26482], gl render */ - CustomData_MeshMasks_update(&scene->customdata_mask, &scene->customdata_mask_modal); - /* TODO(sergey): For now all dependency graphs which are evaluated from - * workspace are considered active. This will work all fine with "locked" - * view layer and time across windows. This is to be granted separately, - * and for until then we have to accept ambiguities when object is shared - * across visible view layers and has overrides on it. - */ - Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); - DEG_make_active(depsgraph); - BKE_scene_graph_update_tagged(depsgraph, bmain); - } + wmWindowManager *wm = CTX_wm_manager(C); + /* The whole idea of locked interface is to prevent viewport and whatever + * thread to modify the same data. Because of this, we can not perform + * dependency graph update. + */ + if (wm->is_interface_locked) { + return; + } + /* Combine datamasks so 1 win doesn't disable UV's in another [#26448]. */ + CustomData_MeshMasks win_combine_v3d_datamask = {0}; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + const Scene *scene = WM_window_get_active_scene(win); + const bScreen *screen = WM_window_get_active_screen(win); + + ED_view3d_screen_datamask(C, scene, screen, &win_combine_v3d_datamask); + } + /* Update all the dependency graphs of visible view layers. */ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + Scene *scene = WM_window_get_active_scene(win); + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + Main *bmain = CTX_data_main(C); + /* Copied to set's in scene_update_tagged_recursive() */ + scene->customdata_mask = win_combine_v3d_datamask; + /* XXX, hack so operators can enforce datamasks [#26482], gl render */ + CustomData_MeshMasks_update(&scene->customdata_mask, &scene->customdata_mask_modal); + /* TODO(sergey): For now all dependency graphs which are evaluated from + * workspace are considered active. This will work all fine with "locked" + * view layer and time across windows. This is to be granted separately, + * and for until then we have to accept ambiguities when object is shared + * across visible view layers and has overrides on it. + */ + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); + DEG_make_active(depsgraph); + BKE_scene_graph_update_tagged(depsgraph, bmain); + } } /** @@ -353,358 +359,354 @@ void wm_event_do_depsgraph(bContext *C) */ void wm_event_do_refresh_wm_and_depsgraph(bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - /* cached: editor refresh callbacks now, they get context */ - for (wmWindow *win = wm->windows.first; win; win = win->next) { - const bScreen *screen = WM_window_get_active_screen(win); - ScrArea *sa; - - CTX_wm_window_set(C, win); - for (sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->do_refresh) { - CTX_wm_area_set(C, sa); - ED_area_do_refresh(C, sa); - } - } - } - - wm_event_do_depsgraph(C); - - CTX_wm_window_set(C, NULL); + wmWindowManager *wm = CTX_wm_manager(C); + /* cached: editor refresh callbacks now, they get context */ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + const bScreen *screen = WM_window_get_active_screen(win); + ScrArea *sa; + + CTX_wm_window_set(C, win); + for (sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->do_refresh) { + CTX_wm_area_set(C, sa); + ED_area_do_refresh(C, sa); + } + } + } + + wm_event_do_depsgraph(C); + + CTX_wm_window_set(C, NULL); } /* called in mainloop */ void wm_event_do_notifiers(bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - wmNotifier *note, *next; - wmWindow *win; + wmWindowManager *wm = CTX_wm_manager(C); + wmNotifier *note, *next; + wmWindow *win; - if (wm == NULL) { - return; - } + if (wm == NULL) { + return; + } - BLI_timer_execute(); + BLI_timer_execute(); - /* disable? - keep for now since its used for window level notifiers. */ + /* disable? - keep for now since its used for window level notifiers. */ #if 1 - /* cache & catch WM level notifiers, such as frame change, scene/screen set */ - for (win = wm->windows.first; win; win = win->next) { - Scene *scene = WM_window_get_active_scene(win); - bool do_anim = false; - - CTX_wm_window_set(C, win); - - for (note = wm->queue.first; note; note = next) { - next = note->next; - - if (note->category == NC_WM) { - if (ELEM(note->data, ND_FILEREAD, ND_FILESAVE)) { - wm->file_saved = 1; - wm_window_title(wm, win); - } - else if (note->data == ND_DATACHANGED) { - wm_window_title(wm, win); - } - } - if (note->window == win) { - if (note->category == NC_SCREEN) { - if (note->data == ND_WORKSPACE_SET) { - WorkSpace *ref_ws = note->reference; - - UI_popup_handlers_remove_all(C, &win->modalhandlers); - - WM_window_set_active_workspace(C, win, ref_ws); - if (G.debug & G_DEBUG_EVENTS) { - printf("%s: Workspace set %p\n", __func__, note->reference); - } - } - else if (note->data == ND_WORKSPACE_DELETE) { - WorkSpace *workspace = note->reference; - - ED_workspace_delete(workspace, CTX_data_main(C), C, wm); // XXX hrms, think this over! - if (G.debug & G_DEBUG_EVENTS) { - printf("%s: Workspace delete %p\n", __func__, workspace); - } - } - else if (note->data == ND_LAYOUTBROWSE) { - bScreen *ref_screen = BKE_workspace_layout_screen_get(note->reference); - - /* free popup handlers only [#35434] */ - UI_popup_handlers_remove_all(C, &win->modalhandlers); - - - ED_screen_change(C, ref_screen); /* XXX hrms, think this over! */ - if (G.debug & G_DEBUG_EVENTS) { - printf("%s: screen set %p\n", __func__, note->reference); - } - } - else if (note->data == ND_LAYOUTDELETE) { - WorkSpace *workspace = WM_window_get_active_workspace(win); - WorkSpaceLayout *layout = note->reference; - - ED_workspace_layout_delete(workspace, layout, C); // XXX hrms, think this over! - if (G.debug & G_DEBUG_EVENTS) { - printf("%s: screen delete %p\n", __func__, note->reference); - } - } - } - } - - if (note->window == win || - (note->window == NULL && (note->reference == NULL || note->reference == scene))) - { - if (note->category == NC_SCENE) { - if (note->data == ND_FRAME) { - do_anim = true; - } - } - } - if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - ED_info_stats_clear(view_layer); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL); - } - } - if (do_anim) { - - /* XXX, quick frame changes can cause a crash if framechange and rendering - * collide (happens on slow scenes), BKE_scene_graph_update_for_newframe can be called - * twice which can depgraph update the same object at once */ - if (G.is_rendering == false) { - /* depsgraph gets called, might send more notifiers */ - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ED_update_for_newframe(CTX_data_main(C), depsgraph); - } - } - } - - /* the notifiers are sent without context, to keep it clean */ - while ((note = BLI_pophead(&wm->queue))) { - for (win = wm->windows.first; win; win = win->next) { - Scene *scene = WM_window_get_active_scene(win); - bScreen *screen = WM_window_get_active_screen(win); - WorkSpace *workspace = WM_window_get_active_workspace(win); - - /* filter out notifiers */ - if (note->category == NC_SCREEN && - note->reference && - note->reference != screen && - note->reference != workspace && - note->reference != WM_window_get_active_layout(win)) - { - /* pass */ - } - else if (note->category == NC_SCENE && note->reference && note->reference != scene) { - /* pass */ - } - else { - ARegion *ar; - - /* XXX context in notifiers? */ - CTX_wm_window_set(C, win); - - /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name + 2, note->category); */ - ED_screen_do_listen(C, note); - - for (ar = screen->regionbase.first; ar; ar = ar->next) { - ED_region_do_listen(win, NULL, ar, note, scene); - } - - ED_screen_areas_iter(win, screen, sa) { - ED_area_do_listen(win, sa, note, scene); - for (ar = sa->regionbase.first; ar; ar = ar->next) { - ED_region_do_listen(win, sa, ar, note, scene); - } - } - } - } - - MEM_freeN(note); - } + /* cache & catch WM level notifiers, such as frame change, scene/screen set */ + for (win = wm->windows.first; win; win = win->next) { + Scene *scene = WM_window_get_active_scene(win); + bool do_anim = false; + + CTX_wm_window_set(C, win); + + for (note = wm->queue.first; note; note = next) { + next = note->next; + + if (note->category == NC_WM) { + if (ELEM(note->data, ND_FILEREAD, ND_FILESAVE)) { + wm->file_saved = 1; + wm_window_title(wm, win); + } + else if (note->data == ND_DATACHANGED) { + wm_window_title(wm, win); + } + } + if (note->window == win) { + if (note->category == NC_SCREEN) { + if (note->data == ND_WORKSPACE_SET) { + WorkSpace *ref_ws = note->reference; + + UI_popup_handlers_remove_all(C, &win->modalhandlers); + + WM_window_set_active_workspace(C, win, ref_ws); + if (G.debug & G_DEBUG_EVENTS) { + printf("%s: Workspace set %p\n", __func__, note->reference); + } + } + else if (note->data == ND_WORKSPACE_DELETE) { + WorkSpace *workspace = note->reference; + + ED_workspace_delete(workspace, CTX_data_main(C), C, wm); // XXX hrms, think this over! + if (G.debug & G_DEBUG_EVENTS) { + printf("%s: Workspace delete %p\n", __func__, workspace); + } + } + else if (note->data == ND_LAYOUTBROWSE) { + bScreen *ref_screen = BKE_workspace_layout_screen_get(note->reference); + + /* free popup handlers only [#35434] */ + UI_popup_handlers_remove_all(C, &win->modalhandlers); + + ED_screen_change(C, ref_screen); /* XXX hrms, think this over! */ + if (G.debug & G_DEBUG_EVENTS) { + printf("%s: screen set %p\n", __func__, note->reference); + } + } + else if (note->data == ND_LAYOUTDELETE) { + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout = note->reference; + + ED_workspace_layout_delete(workspace, layout, C); // XXX hrms, think this over! + if (G.debug & G_DEBUG_EVENTS) { + printf("%s: screen delete %p\n", __func__, note->reference); + } + } + } + } + + if (note->window == win || + (note->window == NULL && (note->reference == NULL || note->reference == scene))) { + if (note->category == NC_SCENE) { + if (note->data == ND_FRAME) { + do_anim = true; + } + } + } + if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) { + ViewLayer *view_layer = CTX_data_view_layer(C); + ED_info_stats_clear(view_layer); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL); + } + } + if (do_anim) { + + /* XXX, quick frame changes can cause a crash if framechange and rendering + * collide (happens on slow scenes), BKE_scene_graph_update_for_newframe can be called + * twice which can depgraph update the same object at once */ + if (G.is_rendering == false) { + /* depsgraph gets called, might send more notifiers */ + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ED_update_for_newframe(CTX_data_main(C), depsgraph); + } + } + } + + /* the notifiers are sent without context, to keep it clean */ + while ((note = BLI_pophead(&wm->queue))) { + for (win = wm->windows.first; win; win = win->next) { + Scene *scene = WM_window_get_active_scene(win); + bScreen *screen = WM_window_get_active_screen(win); + WorkSpace *workspace = WM_window_get_active_workspace(win); + + /* filter out notifiers */ + if (note->category == NC_SCREEN && note->reference && note->reference != screen && + note->reference != workspace && note->reference != WM_window_get_active_layout(win)) { + /* pass */ + } + else if (note->category == NC_SCENE && note->reference && note->reference != scene) { + /* pass */ + } + else { + ARegion *ar; + + /* XXX context in notifiers? */ + CTX_wm_window_set(C, win); + + /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name + 2, note->category); */ + ED_screen_do_listen(C, note); + + for (ar = screen->regionbase.first; ar; ar = ar->next) { + ED_region_do_listen(win, NULL, ar, note, scene); + } + + ED_screen_areas_iter(win, screen, sa) + { + ED_area_do_listen(win, sa, note, scene); + for (ar = sa->regionbase.first; ar; ar = ar->next) { + ED_region_do_listen(win, sa, ar, note, scene); + } + } + } + } + + MEM_freeN(note); + } #endif /* if 1 (postpone disabling for in favor of message-bus), eventually. */ - /* Handle message bus. */ - { - for (win = wm->windows.first; win; win = win->next) { - CTX_wm_window_set(C, win); - WM_msgbus_handle(wm->message_bus, C); - } - CTX_wm_window_set(C, NULL); - } - - wm_event_do_refresh_wm_and_depsgraph(C); - - /* Status bar */ - if (wm->winactive) { - win = wm->winactive; - CTX_wm_window_set(C, win); - WM_window_cursor_keymap_status_refresh(C, win); - CTX_wm_window_set(C, NULL); - } - - /* Autorun warning */ - wm_test_autorun_warning(C); + /* Handle message bus. */ + { + for (win = wm->windows.first; win; win = win->next) { + CTX_wm_window_set(C, win); + WM_msgbus_handle(wm->message_bus, C); + } + CTX_wm_window_set(C, NULL); + } + + wm_event_do_refresh_wm_and_depsgraph(C); + + /* Status bar */ + if (wm->winactive) { + win = wm->winactive; + CTX_wm_window_set(C, win); + WM_window_cursor_keymap_status_refresh(C, win); + CTX_wm_window_set(C, NULL); + } + + /* Autorun warning */ + wm_test_autorun_warning(C); } static int wm_event_always_pass(const wmEvent *event) { - /* some events we always pass on, to ensure proper communication */ - return ISTIMER(event->type) || (event->type == WINDEACTIVATE); + /* some events we always pass on, to ensure proper communication */ + return ISTIMER(event->type) || (event->type == WINDEACTIVATE); } /* ********************* ui handler ******************* */ -static int wm_handler_ui_call(bContext *C, wmEventHandler_UI *handler, const wmEvent *event, int always_pass) +static int wm_handler_ui_call(bContext *C, + wmEventHandler_UI *handler, + const wmEvent *event, + int always_pass) { - ScrArea *area = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - ARegion *menu = CTX_wm_menu(C); - static bool do_wheel_ui = true; - const bool is_wheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN); - int retval; - - /* UI code doesn't handle return values - it just always returns break. - * to make the DBL_CLICK conversion work, we just don't send this to UI, except mouse clicks */ - if (((handler->head.flag & WM_HANDLER_ACCEPT_DBL_CLICK) == 0) && - !ISMOUSE_BUTTON(event->type) && - (event->val == KM_DBL_CLICK)) - { - return WM_HANDLER_CONTINUE; - } - - /* 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 == false) { - if (is_wheel) { - return WM_HANDLER_CONTINUE; - } - else if (wm_event_always_pass(event) == 0) { - do_wheel_ui = true; - } - } - - /* we set context to where ui handler came from */ - if (handler->context.area) { - CTX_wm_area_set(C, handler->context.area); - } - if (handler->context.region) { - CTX_wm_region_set(C, handler->context.region); - } - if (handler->context.menu) { - CTX_wm_menu_set(C, handler->context.menu); - } - - retval = handler->handle_fn(C, event, handler->user_data); - - /* putting back screen context */ - if ((retval != WM_UI_HANDLER_BREAK) || always_pass) { - CTX_wm_area_set(C, area); - CTX_wm_region_set(C, region); - CTX_wm_menu_set(C, menu); - } - else { - /* this special cases is for areas and regions that get removed */ - CTX_wm_area_set(C, NULL); - CTX_wm_region_set(C, NULL); - CTX_wm_menu_set(C, NULL); - } - - if (retval == WM_UI_HANDLER_BREAK) { - return WM_HANDLER_BREAK; - } - - /* event not handled in UI, if wheel then we temporarily disable it */ - if (is_wheel) { - do_wheel_ui = false; - } - - return WM_HANDLER_CONTINUE; + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + ARegion *menu = CTX_wm_menu(C); + static bool do_wheel_ui = true; + const bool is_wheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN); + int retval; + + /* UI code doesn't handle return values - it just always returns break. + * to make the DBL_CLICK conversion work, we just don't send this to UI, except mouse clicks */ + if (((handler->head.flag & WM_HANDLER_ACCEPT_DBL_CLICK) == 0) && !ISMOUSE_BUTTON(event->type) && + (event->val == KM_DBL_CLICK)) { + return WM_HANDLER_CONTINUE; + } + + /* 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 == false) { + if (is_wheel) { + return WM_HANDLER_CONTINUE; + } + else if (wm_event_always_pass(event) == 0) { + do_wheel_ui = true; + } + } + + /* we set context to where ui handler came from */ + if (handler->context.area) { + CTX_wm_area_set(C, handler->context.area); + } + if (handler->context.region) { + CTX_wm_region_set(C, handler->context.region); + } + if (handler->context.menu) { + CTX_wm_menu_set(C, handler->context.menu); + } + + retval = handler->handle_fn(C, event, handler->user_data); + + /* putting back screen context */ + if ((retval != WM_UI_HANDLER_BREAK) || always_pass) { + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + CTX_wm_menu_set(C, menu); + } + else { + /* this special cases is for areas and regions that get removed */ + CTX_wm_area_set(C, NULL); + CTX_wm_region_set(C, NULL); + CTX_wm_menu_set(C, NULL); + } + + if (retval == WM_UI_HANDLER_BREAK) { + return WM_HANDLER_BREAK; + } + + /* event not handled in UI, if wheel then we temporarily disable it */ + if (is_wheel) { + do_wheel_ui = false; + } + + return WM_HANDLER_CONTINUE; } static void wm_handler_ui_cancel(bContext *C) { - wmWindow *win = CTX_wm_window(C); - ARegion *ar = CTX_wm_region(C); - - if (!ar) { - return; - } - - LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, &ar->handlers) { - if (handler_base->type == WM_HANDLER_TYPE_UI) { - wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; - BLI_assert(handler->handle_fn != NULL); - wmEvent event; - wm_event_init_from_window(win, &event); - event.type = EVT_BUT_CANCEL; - handler->handle_fn(C, &event, handler->user_data); - } - } + wmWindow *win = CTX_wm_window(C); + ARegion *ar = CTX_wm_region(C); + + if (!ar) { + return; + } + + LISTBASE_FOREACH_MUTABLE(wmEventHandler *, handler_base, &ar->handlers) + { + if (handler_base->type == WM_HANDLER_TYPE_UI) { + wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; + BLI_assert(handler->handle_fn != NULL); + wmEvent event; + wm_event_init_from_window(win, &event); + event.type = EVT_BUT_CANCEL; + handler->handle_fn(C, &event, handler->user_data); + } + } } /* ********************* operators ******************* */ bool WM_operator_poll(bContext *C, wmOperatorType *ot) { - wmOperatorTypeMacro *otmacro; + wmOperatorTypeMacro *otmacro; - for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { - wmOperatorType *ot_macro = WM_operatortype_find(otmacro->idname, 0); + for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { + wmOperatorType *ot_macro = WM_operatortype_find(otmacro->idname, 0); - if (0 == WM_operator_poll(C, ot_macro)) { - return 0; - } - } + if (0 == WM_operator_poll(C, ot_macro)) { + return 0; + } + } - /* python needs operator type, so we added exception for it */ - if (ot->pyop_poll) { - return ot->pyop_poll(C, ot); - } - else if (ot->poll) { - return ot->poll(C); - } + /* python needs operator type, so we added exception for it */ + if (ot->pyop_poll) { + return ot->pyop_poll(C, ot); + } + else if (ot->poll) { + return ot->poll(C); + } - return 1; + return 1; } /* sets up the new context and calls 'wm_operator_invoke()' with poll_only */ bool WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context) { - return wm_operator_call_internal(C, ot, NULL, NULL, context, true, NULL); + return wm_operator_call_internal(C, ot, NULL, NULL, context, true, NULL); } bool WM_operator_check_ui_empty(wmOperatorType *ot) { - if (ot->macro.first != NULL) { - /* for macros, check all have exec() we can call */ - wmOperatorTypeMacro *otmacro; - for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { - wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0); - if (otm && !WM_operator_check_ui_empty(otm)) { - return false; - } - } - return true; - } - - /* Assume a ui callback will draw something. */ - if (ot->ui) { - return false; - } - - PointerRNA ptr; - WM_operator_properties_create_ptr(&ptr, ot); - RNA_STRUCT_BEGIN (&ptr, prop) - { - int flag = RNA_property_flag(prop); - if (flag & PROP_HIDDEN) { - continue; - } - return false; - } - RNA_STRUCT_END; - return true; + if (ot->macro.first != NULL) { + /* for macros, check all have exec() we can call */ + wmOperatorTypeMacro *otmacro; + for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { + wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0); + if (otm && !WM_operator_check_ui_empty(otm)) { + return false; + } + } + return true; + } + + /* Assume a ui callback will draw something. */ + if (ot->ui) { + return false; + } + + PointerRNA ptr; + WM_operator_properties_create_ptr(&ptr, ot); + RNA_STRUCT_BEGIN (&ptr, prop) { + int flag = RNA_property_flag(prop); + if (flag & PROP_HIDDEN) { + continue; + } + return false; + } + RNA_STRUCT_END; + return true; } /** @@ -714,57 +716,75 @@ bool WM_operator_check_ui_empty(wmOperatorType *ot) */ void WM_operator_region_active_win_set(bContext *C) { - ScrArea *sa = CTX_wm_area(C); - if (sa) { - ARegion *ar = CTX_wm_region(C); - if (ar && ar->regiontype == RGN_TYPE_WINDOW) { - sa->region_active_win = BLI_findindex(&sa->regionbase, ar); - } - } + ScrArea *sa = CTX_wm_area(C); + if (sa) { + ARegion *ar = CTX_wm_region(C); + if (ar && ar->regiontype == RGN_TYPE_WINDOW) { + sa->region_active_win = BLI_findindex(&sa->regionbase, ar); + } + } } /* for debugging only, getting inspecting events manually is tedious */ void WM_event_print(const wmEvent *event) { - if (event) { - const char *unknown = "UNKNOWN"; - const char *type_id = unknown; - const char *val_id = unknown; - - RNA_enum_identifier(rna_enum_event_type_items, event->type, &type_id); - RNA_enum_identifier(rna_enum_event_value_items, event->val, &val_id); - - printf("wmEvent type:%d / %s, val:%d / %s,\n" - " shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d,\n" - " mouse:(%d,%d), ascii:'%c', utf8:'%.*s', keymap_idname:%s, pointer:%p\n", - event->type, type_id, event->val, val_id, - event->shift, event->ctrl, event->alt, event->oskey, event->keymodifier, - event->x, event->y, event->ascii, - BLI_str_utf8_size(event->utf8_buf), event->utf8_buf, - event->keymap_idname, (const void *)event); + if (event) { + const char *unknown = "UNKNOWN"; + const char *type_id = unknown; + const char *val_id = unknown; + + RNA_enum_identifier(rna_enum_event_type_items, event->type, &type_id); + RNA_enum_identifier(rna_enum_event_value_items, event->val, &val_id); + + printf( + "wmEvent type:%d / %s, val:%d / %s,\n" + " shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d,\n" + " mouse:(%d,%d), ascii:'%c', utf8:'%.*s', keymap_idname:%s, pointer:%p\n", + event->type, + type_id, + event->val, + val_id, + event->shift, + event->ctrl, + event->alt, + event->oskey, + event->keymodifier, + event->x, + event->y, + event->ascii, + BLI_str_utf8_size(event->utf8_buf), + event->utf8_buf, + event->keymap_idname, + (const void *)event); #ifdef WITH_INPUT_NDOF - if (ISNDOF(event->type)) { - const wmNDOFMotionData *ndof = event->customdata; - if (event->type == NDOF_MOTION) { - printf(" ndof: rot: (%.4f %.4f %.4f), tx: (%.4f %.4f %.4f), dt: %.4f, progress: %u\n", - UNPACK3(ndof->rvec), UNPACK3(ndof->tvec), ndof->dt, ndof->progress); - } - else { - /* ndof buttons printed already */ - } - } + if (ISNDOF(event->type)) { + const wmNDOFMotionData *ndof = event->customdata; + if (event->type == NDOF_MOTION) { + printf(" ndof: rot: (%.4f %.4f %.4f), tx: (%.4f %.4f %.4f), dt: %.4f, progress: %u\n", + UNPACK3(ndof->rvec), + UNPACK3(ndof->tvec), + ndof->dt, + ndof->progress); + } + else { + /* ndof buttons printed already */ + } + } #endif /* WITH_INPUT_NDOF */ - if (event->tablet_data) { - const wmTabletData *wmtab = event->tablet_data; - printf(" tablet: active: %d, pressure %.4f, tilt: (%.4f %.4f)\n", - wmtab->Active, wmtab->Pressure, wmtab->Xtilt, wmtab->Ytilt); - } - } - else { - printf("wmEvent - NULL\n"); - } + if (event->tablet_data) { + const wmTabletData *wmtab = event->tablet_data; + printf(" tablet: active: %d, pressure %.4f, tilt: (%.4f %.4f)\n", + wmtab->Active, + wmtab->Pressure, + wmtab->Xtilt, + wmtab->Ytilt); + } + } + else { + printf("wmEvent - NULL\n"); + } } /** @@ -772,120 +792,120 @@ void WM_event_print(const wmEvent *event) */ void WM_report_banner_show(void) { - wmWindowManager *wm = G_MAIN->wm.first; - ReportList *wm_reports = &wm->reports; - ReportTimerInfo *rti; + wmWindowManager *wm = G_MAIN->wm.first; + ReportList *wm_reports = &wm->reports; + ReportTimerInfo *rti; - /* After adding reports to the global list, reset the report timer. */ - WM_event_remove_timer(wm, NULL, wm_reports->reporttimer); + /* After adding reports to the global list, reset the report timer. */ + WM_event_remove_timer(wm, NULL, wm_reports->reporttimer); - /* Records time since last report was added */ - wm_reports->reporttimer = WM_event_add_timer(wm, wm->winactive, TIMERREPORT, 0.05); + /* Records time since last report was added */ + wm_reports->reporttimer = WM_event_add_timer(wm, wm->winactive, TIMERREPORT, 0.05); - rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); - wm_reports->reporttimer->customdata = rti; + rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); + wm_reports->reporttimer->customdata = rti; } bool WM_event_is_last_mousemove(const wmEvent *event) { - while ((event = event->next)) { - if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - return false; - } - } - return true; + while ((event = event->next)) { + if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + return false; + } + } + return true; } #ifdef WITH_INPUT_NDOF void WM_ndof_deadzone_set(float deadzone) { - GHOST_setNDOFDeadZone(deadzone); + GHOST_setNDOFDeadZone(deadzone); } #endif static void wm_add_reports(ReportList *reports) { - /* if the caller owns them, handle this */ - if (reports->list.first && (reports->flag & RPT_OP_HOLD) == 0) { - wmWindowManager *wm = G_MAIN->wm.first; + /* if the caller owns them, handle this */ + if (reports->list.first && (reports->flag & RPT_OP_HOLD) == 0) { + wmWindowManager *wm = G_MAIN->wm.first; - /* add reports to the global list, otherwise they are not seen */ - BLI_movelisttolist(&wm->reports.list, &reports->list); + /* add reports to the global list, otherwise they are not seen */ + BLI_movelisttolist(&wm->reports.list, &reports->list); - WM_report_banner_show(); - } + WM_report_banner_show(); + } } void WM_report(ReportType type, const char *message) { - ReportList reports; + ReportList reports; - BKE_reports_init(&reports, RPT_STORE); - BKE_report(&reports, type, message); + BKE_reports_init(&reports, RPT_STORE); + BKE_report(&reports, type, message); - wm_add_reports(&reports); + wm_add_reports(&reports); - BKE_reports_clear(&reports); + BKE_reports_clear(&reports); } void WM_reportf(ReportType type, const char *format, ...) { - DynStr *ds; - va_list args; + DynStr *ds; + va_list args; - ds = BLI_dynstr_new(); - va_start(args, format); - BLI_dynstr_vappendf(ds, format, args); - va_end(args); + ds = BLI_dynstr_new(); + va_start(args, format); + BLI_dynstr_vappendf(ds, format, args); + va_end(args); - char *str = BLI_dynstr_get_cstring(ds); - WM_report(type, str); - MEM_freeN(str); + char *str = BLI_dynstr_get_cstring(ds); + WM_report(type, str); + MEM_freeN(str); - BLI_dynstr_free(ds); + BLI_dynstr_free(ds); } /* (caller_owns_reports == true) when called from python */ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool caller_owns_reports) { - if (G.background == 0 && caller_owns_reports == false) { /* popup */ - if (op->reports->list.first) { - /* FIXME, temp setting window, see other call to UI_popup_menu_reports for why */ - wmWindow *win_prev = CTX_wm_window(C); - ScrArea *area_prev = CTX_wm_area(C); - ARegion *ar_prev = CTX_wm_region(C); - - if (win_prev == NULL) { - CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); - } - - UI_popup_menu_reports(C, op->reports); - - CTX_wm_window_set(C, win_prev); - CTX_wm_area_set(C, area_prev); - CTX_wm_region_set(C, ar_prev); - } - } - - if (retval & OPERATOR_FINISHED) { - CLOG_STR_INFO_N(WM_LOG_OPERATORS, 1, WM_operator_pystring(C, op, false, true)); - - if (caller_owns_reports == false) { - BKE_reports_print(op->reports, RPT_DEBUG); /* print out reports to console. */ - } - - if (op->type->flag & OPTYPE_REGISTER) { - if (G.background == 0) { /* ends up printing these in the terminal, gets annoying */ - /* Report the python string representation of the operator */ - char *buf = WM_operator_pystring(C, op, false, true); - BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf); - MEM_freeN(buf); - } - } - } - - /* if the caller owns them, handle this */ - wm_add_reports(op->reports); + if (G.background == 0 && caller_owns_reports == false) { /* popup */ + if (op->reports->list.first) { + /* FIXME, temp setting window, see other call to UI_popup_menu_reports for why */ + wmWindow *win_prev = CTX_wm_window(C); + ScrArea *area_prev = CTX_wm_area(C); + ARegion *ar_prev = CTX_wm_region(C); + + if (win_prev == NULL) { + CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); + } + + UI_popup_menu_reports(C, op->reports); + + CTX_wm_window_set(C, win_prev); + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, ar_prev); + } + } + + if (retval & OPERATOR_FINISHED) { + CLOG_STR_INFO_N(WM_LOG_OPERATORS, 1, WM_operator_pystring(C, op, false, true)); + + if (caller_owns_reports == false) { + BKE_reports_print(op->reports, RPT_DEBUG); /* print out reports to console. */ + } + + if (op->type->flag & OPTYPE_REGISTER) { + if (G.background == 0) { /* ends up printing these in the terminal, gets annoying */ + /* Report the python string representation of the operator */ + char *buf = WM_operator_pystring(C, op, false, true); + BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf); + MEM_freeN(buf); + } + } + } + + /* if the caller owns them, handle this */ + wm_add_reports(op->reports); } /** @@ -894,152 +914,156 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca */ static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot) { - /* Check undo flag here since undo operators are also added to the list, - * to support checking if the same operator is run twice. */ - return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO)); + /* Check undo flag here since undo operators are also added to the list, + * to support checking if the same operator is run twice. */ + return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO)); } static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat, const bool store) { - wmWindowManager *wm = CTX_wm_manager(C); - enum { NOP, SET, CLEAR, } hud_status = NOP; - - op->customdata = NULL; - - if (store) { - WM_operator_last_properties_store(op); - } - - /* we don't want to do undo pushes for operators that are being - * called from operators that already do an undo push. usually - * this will happen for python operators that call C operators */ - if (wm->op_undo_depth == 0) { - if (op->type->flag & OPTYPE_UNDO) { - ED_undo_push_op(C, op); - if (repeat == 0) { - hud_status = CLEAR; - } - } - else if (op->type->flag & OPTYPE_UNDO_GROUPED) { - ED_undo_grouped_push_op(C, op); - if (repeat == 0) { - hud_status = CLEAR; - } - } - - } - - if (repeat == 0) { - if (G.debug & G_DEBUG_WM) { - char *buf = WM_operator_pystring(C, op, false, true); - BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf); - MEM_freeN(buf); - } - - if (wm_operator_register_check(wm, op->type)) { - /* take ownership of reports (in case python provided own) */ - op->reports->flag |= RPT_FREE; - - wm_operator_register(C, op); - WM_operator_region_active_win_set(C); - - if (WM_operator_last_redo(C) == op) { - /* Show the redo panel. */ - hud_status = SET; - } - } - else { - WM_operator_free(op); - } - } - - if (hud_status != NOP) { - if (hud_status == SET) { - ScrArea *sa = CTX_wm_area(C); - if (sa) { - ED_area_type_hud_ensure(C, sa); - } - } - else if (hud_status == CLEAR) { - ED_area_type_hud_clear(wm, NULL); - } - else { - BLI_assert(0); - } - } + wmWindowManager *wm = CTX_wm_manager(C); + enum { + NOP, + SET, + CLEAR, + } hud_status = NOP; + + op->customdata = NULL; + + if (store) { + WM_operator_last_properties_store(op); + } + + /* we don't want to do undo pushes for operators that are being + * called from operators that already do an undo push. usually + * this will happen for python operators that call C operators */ + if (wm->op_undo_depth == 0) { + if (op->type->flag & OPTYPE_UNDO) { + ED_undo_push_op(C, op); + if (repeat == 0) { + hud_status = CLEAR; + } + } + else if (op->type->flag & OPTYPE_UNDO_GROUPED) { + ED_undo_grouped_push_op(C, op); + if (repeat == 0) { + hud_status = CLEAR; + } + } + } + + if (repeat == 0) { + if (G.debug & G_DEBUG_WM) { + char *buf = WM_operator_pystring(C, op, false, true); + BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf); + MEM_freeN(buf); + } + + if (wm_operator_register_check(wm, op->type)) { + /* take ownership of reports (in case python provided own) */ + op->reports->flag |= RPT_FREE; + + wm_operator_register(C, op); + WM_operator_region_active_win_set(C); + + if (WM_operator_last_redo(C) == op) { + /* Show the redo panel. */ + hud_status = SET; + } + } + else { + WM_operator_free(op); + } + } + + if (hud_status != NOP) { + if (hud_status == SET) { + ScrArea *sa = CTX_wm_area(C); + if (sa) { + ED_area_type_hud_ensure(C, sa); + } + } + else if (hud_status == CLEAR) { + ED_area_type_hud_clear(wm, NULL); + } + else { + BLI_assert(0); + } + } } /* if repeat is true, it doesn't register again, nor does it free */ -static int wm_operator_exec( - bContext *C, wmOperator *op, - const bool repeat, const bool use_repeat_op_flag, const bool store) +static int wm_operator_exec(bContext *C, + wmOperator *op, + const bool repeat, + const bool use_repeat_op_flag, + const bool store) { - wmWindowManager *wm = CTX_wm_manager(C); - int retval = OPERATOR_CANCELLED; - - CTX_wm_operator_poll_msg_set(C, NULL); - - if (op == NULL || op->type == NULL) { - return retval; - } - - if (0 == WM_operator_poll(C, op->type)) { - return retval; - } - - if (op->type->exec) { - if (op->type->flag & OPTYPE_UNDO) { - wm->op_undo_depth++; - } - - if (repeat && use_repeat_op_flag) { - op->flag |= OP_IS_REPEAT; - } - retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); - if (repeat && use_repeat_op_flag) { - op->flag &= ~OP_IS_REPEAT; - } - - if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { - wm->op_undo_depth--; - } - } - - /* XXX Disabled the repeat check to address part 2 of #31840. - * Carefully checked all calls to wm_operator_exec and WM_operator_repeat, don't see any reason - * why this was needed, but worth to note it in case something turns bad. (mont29) */ - if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED) /* && repeat == 0 */) { - wm_operator_reports(C, op, retval, false); - } - - if (retval & OPERATOR_FINISHED) { - wm_operator_finished(C, op, repeat, store && wm->op_undo_depth == 0); - } - else if (repeat == 0) { - /* warning: modal from exec is bad practice, but avoid crashing. */ - if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { - WM_operator_free(op); - } - } - - return retval | OPERATOR_HANDLED; - + wmWindowManager *wm = CTX_wm_manager(C); + int retval = OPERATOR_CANCELLED; + + CTX_wm_operator_poll_msg_set(C, NULL); + + if (op == NULL || op->type == NULL) { + return retval; + } + + if (0 == WM_operator_poll(C, op->type)) { + return retval; + } + + if (op->type->exec) { + if (op->type->flag & OPTYPE_UNDO) { + wm->op_undo_depth++; + } + + if (repeat && use_repeat_op_flag) { + op->flag |= OP_IS_REPEAT; + } + retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + if (repeat && use_repeat_op_flag) { + op->flag &= ~OP_IS_REPEAT; + } + + if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { + wm->op_undo_depth--; + } + } + + /* XXX Disabled the repeat check to address part 2 of #31840. + * Carefully checked all calls to wm_operator_exec and WM_operator_repeat, don't see any reason + * why this was needed, but worth to note it in case something turns bad. (mont29) */ + if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED) /* && repeat == 0 */) { + wm_operator_reports(C, op, retval, false); + } + + if (retval & OPERATOR_FINISHED) { + wm_operator_finished(C, op, repeat, store && wm->op_undo_depth == 0); + } + else if (repeat == 0) { + /* warning: modal from exec is bad practice, but avoid crashing. */ + if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { + WM_operator_free(op); + } + } + + return retval | OPERATOR_HANDLED; } /* simply calls exec with basic checks */ static int wm_operator_exec_notest(bContext *C, wmOperator *op) { - int retval = OPERATOR_CANCELLED; + int retval = OPERATOR_CANCELLED; - if (op == NULL || op->type == NULL || op->type->exec == NULL) { - return retval; - } + if (op == NULL || op->type == NULL || op->type->exec == NULL) { + return retval; + } - retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); + retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); - return retval; + return retval; } /** @@ -1048,15 +1072,14 @@ static int wm_operator_exec_notest(bContext *C, wmOperator *op) * \param store: Store settings for re-use. * * warning: do not use this within an operator to call its self! [#29537] */ -int WM_operator_call_ex(bContext *C, wmOperator *op, - const bool store) +int WM_operator_call_ex(bContext *C, wmOperator *op, const bool store) { - return wm_operator_exec(C, op, false, false, store); + return wm_operator_exec(C, op, false, false, store); } int WM_operator_call(bContext *C, wmOperator *op) { - return WM_operator_call_ex(C, op, false); + return WM_operator_call_ex(C, op, false); } /** @@ -1066,7 +1089,7 @@ int WM_operator_call(bContext *C, wmOperator *op) */ int WM_operator_call_notest(bContext *C, wmOperator *op) { - return wm_operator_exec_notest(C, op); + return wm_operator_exec_notest(C, op); } /** @@ -1074,11 +1097,11 @@ int WM_operator_call_notest(bContext *C, wmOperator *op) */ int WM_operator_repeat(bContext *C, wmOperator *op) { - return wm_operator_exec(C, op, true, true, true); + return wm_operator_exec(C, op, true, true, true); } int WM_operator_repeat_interactive(bContext *C, wmOperator *op) { - return wm_operator_exec(C, op, true, false, true); + return wm_operator_exec(C, op, true, false, true); } /** * \return true if #WM_operator_repeat can run @@ -1088,240 +1111,240 @@ int WM_operator_repeat_interactive(bContext *C, wmOperator *op) */ bool WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op) { - if (op->type->exec != NULL) { - return true; - } - else if (op->opm) { - /* for macros, check all have exec() we can call */ - wmOperatorTypeMacro *otmacro; - for (otmacro = op->opm->type->macro.first; otmacro; otmacro = otmacro->next) { - wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0); - if (otm && otm->exec == NULL) { - return false; - } - } - return true; - } - - return false; + if (op->type->exec != NULL) { + return true; + } + else if (op->opm) { + /* for macros, check all have exec() we can call */ + wmOperatorTypeMacro *otmacro; + for (otmacro = op->opm->type->macro.first; otmacro; otmacro = otmacro->next) { + wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0); + if (otm && otm->exec == NULL) { + return false; + } + } + return true; + } + + return false; } bool WM_operator_is_repeat(const bContext *C, const wmOperator *op) { - /* may be in the operators list or not */ - wmOperator *op_prev; - if (op->prev == NULL && op->next == NULL) { - wmWindowManager *wm = CTX_wm_manager(C); - op_prev = wm->operators.last; - } - else { - op_prev = op->prev; - } - return (op_prev && (op->type == op_prev->type)); + /* may be in the operators list or not */ + wmOperator *op_prev; + if (op->prev == NULL && op->next == NULL) { + wmWindowManager *wm = CTX_wm_manager(C); + op_prev = wm->operators.last; + } + else { + op_prev = op->prev; + } + return (op_prev && (op->type == op_prev->type)); } -static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, - PointerRNA *properties, ReportList *reports) +static wmOperator *wm_operator_create(wmWindowManager *wm, + wmOperatorType *ot, + PointerRNA *properties, + ReportList *reports) { - /* XXX operatortype names are static still. for debug */ - wmOperator *op = MEM_callocN(sizeof(wmOperator), ot->idname); - - /* XXX adding new operator could be function, only happens here now */ - op->type = ot; - BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME); - - /* initialize properties, either copy or create */ - op->ptr = MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA"); - if (properties && properties->data) { - op->properties = IDP_CopyProperty(properties->data); - } - else { - IDPropertyTemplate val = {0}; - op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); - } - RNA_pointer_create(&wm->id, ot->srna, op->properties, op->ptr); - - /* initialize error reports */ - if (reports) { - op->reports = reports; /* must be initialized already */ - } - else { - op->reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); - BKE_reports_init(op->reports, RPT_STORE | RPT_FREE); - } - - /* recursive filling of operator macro list */ - if (ot->macro.first) { - static wmOperator *motherop = NULL; - wmOperatorTypeMacro *otmacro; - int root = 0; - - /* ensure all ops are in execution order in 1 list */ - if (motherop == NULL) { - motherop = op; - root = 1; - } - - - /* if properties exist, it will contain everything needed */ - if (properties) { - otmacro = ot->macro.first; - - RNA_STRUCT_BEGIN (properties, prop) - { - - if (otmacro == NULL) { - break; - } - - /* skip invalid properties */ - if (STREQ(RNA_property_identifier(prop), otmacro->idname)) { - wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0); - PointerRNA someptr = RNA_property_pointer_get(properties, prop); - wmOperator *opm = wm_operator_create(wm, otm, &someptr, NULL); - - IDP_ReplaceGroupInGroup(opm->properties, otmacro->properties); - - BLI_addtail(&motherop->macro, opm); - opm->opm = motherop; /* pointer to mom, for modal() */ - - otmacro = otmacro->next; - } - } - RNA_STRUCT_END; - } - else { - for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { - wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0); - wmOperator *opm = wm_operator_create(wm, otm, otmacro->ptr, NULL); - - BLI_addtail(&motherop->macro, opm); - opm->opm = motherop; /* pointer to mom, for modal() */ - } - } - - if (root) { - motherop = NULL; - } - } - - WM_operator_properties_sanitize(op->ptr, 0); - - return op; + /* XXX operatortype names are static still. for debug */ + wmOperator *op = MEM_callocN(sizeof(wmOperator), ot->idname); + + /* XXX adding new operator could be function, only happens here now */ + op->type = ot; + BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME); + + /* initialize properties, either copy or create */ + op->ptr = MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA"); + if (properties && properties->data) { + op->properties = IDP_CopyProperty(properties->data); + } + else { + IDPropertyTemplate val = {0}; + op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); + } + RNA_pointer_create(&wm->id, ot->srna, op->properties, op->ptr); + + /* initialize error reports */ + if (reports) { + op->reports = reports; /* must be initialized already */ + } + else { + op->reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); + BKE_reports_init(op->reports, RPT_STORE | RPT_FREE); + } + + /* recursive filling of operator macro list */ + if (ot->macro.first) { + static wmOperator *motherop = NULL; + wmOperatorTypeMacro *otmacro; + int root = 0; + + /* ensure all ops are in execution order in 1 list */ + if (motherop == NULL) { + motherop = op; + root = 1; + } + + /* if properties exist, it will contain everything needed */ + if (properties) { + otmacro = ot->macro.first; + + RNA_STRUCT_BEGIN (properties, prop) { + + if (otmacro == NULL) { + break; + } + + /* skip invalid properties */ + if (STREQ(RNA_property_identifier(prop), otmacro->idname)) { + wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0); + PointerRNA someptr = RNA_property_pointer_get(properties, prop); + wmOperator *opm = wm_operator_create(wm, otm, &someptr, NULL); + + IDP_ReplaceGroupInGroup(opm->properties, otmacro->properties); + + BLI_addtail(&motherop->macro, opm); + opm->opm = motherop; /* pointer to mom, for modal() */ + + otmacro = otmacro->next; + } + } + RNA_STRUCT_END; + } + else { + for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { + wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0); + wmOperator *opm = wm_operator_create(wm, otm, otmacro->ptr, NULL); + + BLI_addtail(&motherop->macro, opm); + opm->opm = motherop; /* pointer to mom, for modal() */ + } + } + + if (root) { + motherop = NULL; + } + } + + WM_operator_properties_sanitize(op->ptr, 0); + + return op; } static void wm_region_mouse_co(bContext *C, wmEvent *event) { - ARegion *ar = CTX_wm_region(C); - if (ar) { - /* compatibility convention */ - 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; - } + ARegion *ar = CTX_wm_region(C); + if (ar) { + /* compatibility convention */ + 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; + } } #if 1 /* may want to disable operator remembering previous state for testing */ static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_properties) { - bool changed = false; - IDPropertyTemplate val = {0}; - IDProperty *replaceprops = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); - PropertyRNA *iterprop; - - CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname); - - iterprop = RNA_struct_iterator_property(op->type->srna); - - RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) - { - PropertyRNA *prop = itemptr.data; - if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) { - if (!RNA_property_is_set(op->ptr, prop)) { /* don't override a setting already set */ - const char *identifier = RNA_property_identifier(prop); - IDProperty *idp_src = IDP_GetPropertyFromGroup(last_properties, identifier); - if (idp_src) { - IDProperty *idp_dst = IDP_CopyProperty(idp_src); - - /* note - in the future this may need to be done recursively, - * but for now RNA doesn't access nested operators */ - idp_dst->flag |= IDP_FLAG_GHOST; - - /* add to temporary group instead of immediate replace, - * because we are iterating over this group */ - IDP_AddToGroup(replaceprops, idp_dst); - changed = true; - } - } - } - } - RNA_PROP_END; - - IDP_MergeGroup(op->properties, replaceprops, true); - IDP_FreeProperty(replaceprops); - MEM_freeN(replaceprops); - return changed; + bool changed = false; + IDPropertyTemplate val = {0}; + IDProperty *replaceprops = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); + PropertyRNA *iterprop; + + CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname); + + iterprop = RNA_struct_iterator_property(op->type->srna); + + RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) { + PropertyRNA *prop = itemptr.data; + if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) { + if (!RNA_property_is_set(op->ptr, prop)) { /* don't override a setting already set */ + const char *identifier = RNA_property_identifier(prop); + IDProperty *idp_src = IDP_GetPropertyFromGroup(last_properties, identifier); + if (idp_src) { + IDProperty *idp_dst = IDP_CopyProperty(idp_src); + + /* note - in the future this may need to be done recursively, + * but for now RNA doesn't access nested operators */ + idp_dst->flag |= IDP_FLAG_GHOST; + + /* add to temporary group instead of immediate replace, + * because we are iterating over this group */ + IDP_AddToGroup(replaceprops, idp_dst); + changed = true; + } + } + } + } + RNA_PROP_END; + + IDP_MergeGroup(op->properties, replaceprops, true); + IDP_FreeProperty(replaceprops); + MEM_freeN(replaceprops); + return changed; } bool WM_operator_last_properties_init(wmOperator *op) { - bool changed = false; - if (op->type->last_properties) { - changed |= operator_last_properties_init_impl(op, op->type->last_properties); - for (wmOperator *opm = op->macro.first; opm; opm = opm->next) { - IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, opm->idname); - if (idp_src) { - changed |= operator_last_properties_init_impl(opm, idp_src); - } - } - } - return changed; + bool changed = false; + if (op->type->last_properties) { + changed |= operator_last_properties_init_impl(op, op->type->last_properties); + for (wmOperator *opm = op->macro.first; opm; opm = opm->next) { + IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, opm->idname); + if (idp_src) { + changed |= operator_last_properties_init_impl(opm, idp_src); + } + } + } + return changed; } bool WM_operator_last_properties_store(wmOperator *op) { - if (op->type->last_properties) { - IDP_FreeProperty(op->type->last_properties); - MEM_freeN(op->type->last_properties); - op->type->last_properties = NULL; - } - - if (op->properties) { - CLOG_INFO(WM_LOG_OPERATORS, 1, "storing properties for '%s'", op->type->idname); - op->type->last_properties = IDP_CopyProperty(op->properties); - } - - if (op->macro.first != NULL) { - for (wmOperator *opm = op->macro.first; opm; opm = opm->next) { - if (opm->properties) { - if (op->type->last_properties == NULL) { - op->type->last_properties = IDP_New(IDP_GROUP, &(IDPropertyTemplate){0}, "wmOperatorProperties"); - } - IDProperty *idp_macro = IDP_CopyProperty(opm->properties); - STRNCPY(idp_macro->name, opm->idname); - IDP_ReplaceInGroup(op->type->last_properties, idp_macro); - } - } - } - - return (op->type->last_properties != NULL); + if (op->type->last_properties) { + IDP_FreeProperty(op->type->last_properties); + MEM_freeN(op->type->last_properties); + op->type->last_properties = NULL; + } + + if (op->properties) { + CLOG_INFO(WM_LOG_OPERATORS, 1, "storing properties for '%s'", op->type->idname); + op->type->last_properties = IDP_CopyProperty(op->properties); + } + + if (op->macro.first != NULL) { + for (wmOperator *opm = op->macro.first; opm; opm = opm->next) { + if (opm->properties) { + if (op->type->last_properties == NULL) { + op->type->last_properties = IDP_New( + IDP_GROUP, &(IDPropertyTemplate){0}, "wmOperatorProperties"); + } + IDProperty *idp_macro = IDP_CopyProperty(opm->properties); + STRNCPY(idp_macro->name, opm->idname); + IDP_ReplaceInGroup(op->type->last_properties, idp_macro); + } + } + } + + return (op->type->last_properties != NULL); } #else bool WM_operator_last_properties_init(wmOperator *UNUSED(op)) { - return false; + return false; } bool WM_operator_last_properties_store(wmOperator *UNUSED(op)) { - return false; + return false; } #endif @@ -1329,151 +1352,158 @@ bool WM_operator_last_properties_store(wmOperator *UNUSED(op)) /** * Also used for exec when 'event' is NULL. */ -static int wm_operator_invoke( - bContext *C, wmOperatorType *ot, wmEvent *event, - PointerRNA *properties, ReportList *reports, - const bool poll_only, bool use_last_properties) +static int wm_operator_invoke(bContext *C, + wmOperatorType *ot, + wmEvent *event, + PointerRNA *properties, + ReportList *reports, + const bool poll_only, + bool use_last_properties) { - int retval = OPERATOR_PASS_THROUGH; - - /* this is done because complicated setup is done to call this function that is better not duplicated */ - if (poll_only) { - return WM_operator_poll(C, ot); - } - - if (WM_operator_poll(C, ot)) { - wmWindowManager *wm = CTX_wm_manager(C); - wmOperator *op = wm_operator_create(wm, ot, properties, reports); /* if reports == NULL, they'll be initialized */ - const bool is_nested_call = (wm->op_undo_depth != 0); - - if (event != NULL) { - op->flag |= OP_IS_INVOKE; - } - - /* initialize setting from previous run */ - if (!is_nested_call && use_last_properties) { /* not called by py script */ - WM_operator_last_properties_init(op); - } - - if ((event == NULL) || (event->type != MOUSEMOVE)) { - CLOG_INFO(WM_LOG_HANDLERS, 2, - "handle evt %d win %p op %s", - event ? event->type : 0, CTX_wm_screen(C)->active_region, ot->idname); - } - - if (op->type->invoke && event) { - wm_region_mouse_co(C, event); - - if (op->type->flag & OPTYPE_UNDO) { - wm->op_undo_depth++; - } - - retval = op->type->invoke(C, op, event); - OPERATOR_RETVAL_CHECK(retval); - - if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { - wm->op_undo_depth--; - } - } - else if (op->type->exec) { - if (op->type->flag & OPTYPE_UNDO) { - wm->op_undo_depth++; - } - - retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); - - if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { - wm->op_undo_depth--; - } - } - else { - /* debug, important to leave a while, should never happen */ - CLOG_ERROR(WM_LOG_OPERATORS, "invalid operator call '%s'", op->idname); - } - - /* Note, if the report is given as an argument then assume the caller will deal with displaying them - * currently python only uses this */ - if (!(retval & OPERATOR_HANDLED) && (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED))) { - /* only show the report if the report list was not given in the function */ - wm_operator_reports(C, op, retval, (reports != NULL)); - } - - if (retval & OPERATOR_HANDLED) { - /* do nothing, wm_operator_exec() has been called somewhere */ - } - else if (retval & OPERATOR_FINISHED) { - const bool store = !is_nested_call && use_last_properties; - wm_operator_finished(C, op, false, store); - } - else if (retval & OPERATOR_RUNNING_MODAL) { - /* take ownership of reports (in case python provided own) */ - op->reports->flag |= RPT_FREE; - - /* grab cursor during blocking modal ops (X11) - * Also check for macro - */ - if (ot->flag & OPTYPE_BLOCKING || (op->opm && op->opm->type->flag & OPTYPE_BLOCKING)) { - int bounds[4] = {-1, -1, -1, -1}; - bool wrap; - - if (event == NULL) { - wrap = false; - } - else if (op->opm) { - wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR)); - } - else { - wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->flag & OP_IS_MODAL_GRAB_CURSOR) || (ot->flag & OPTYPE_GRAB_CURSOR)); - } - - /* exception, cont. grab in header is annoying */ - if (wrap) { - ARegion *ar = CTX_wm_region(C); - if (ar && ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) { - wrap = false; - } - } - - if (wrap) { - const rcti *winrect = NULL; - ARegion *ar = CTX_wm_region(C); - ScrArea *sa = CTX_wm_area(C); - - if (ar && ar->regiontype == RGN_TYPE_WINDOW && - BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) - { - winrect = &ar->winrct; - } - else if (sa && BLI_rcti_isect_pt_v(&sa->totrct, &event->x)) { - winrect = &sa->totrct; - } - - if (winrect) { - bounds[0] = winrect->xmin; - bounds[1] = winrect->ymax; - bounds[2] = winrect->xmax; - bounds[3] = winrect->ymin; - } - } - - WM_cursor_grab_enable(CTX_wm_window(C), wrap, false, bounds); - } - - /* cancel UI handlers, typically tooltips that can hang around - * while dragging the view or worse, that stay there permanently - * after the modal operator has swallowed all events and passed - * none to the UI handler */ - wm_handler_ui_cancel(C); - } - else { - WM_operator_free(op); - } - } - - return retval; + int retval = OPERATOR_PASS_THROUGH; + + /* this is done because complicated setup is done to call this function that is better not duplicated */ + if (poll_only) { + return WM_operator_poll(C, ot); + } + + if (WM_operator_poll(C, ot)) { + wmWindowManager *wm = CTX_wm_manager(C); + wmOperator *op = wm_operator_create( + wm, ot, properties, reports); /* if reports == NULL, they'll be initialized */ + const bool is_nested_call = (wm->op_undo_depth != 0); + + if (event != NULL) { + op->flag |= OP_IS_INVOKE; + } + + /* initialize setting from previous run */ + if (!is_nested_call && use_last_properties) { /* not called by py script */ + WM_operator_last_properties_init(op); + } + + if ((event == NULL) || (event->type != MOUSEMOVE)) { + CLOG_INFO(WM_LOG_HANDLERS, + 2, + "handle evt %d win %p op %s", + event ? event->type : 0, + CTX_wm_screen(C)->active_region, + ot->idname); + } + + if (op->type->invoke && event) { + wm_region_mouse_co(C, event); + + if (op->type->flag & OPTYPE_UNDO) { + wm->op_undo_depth++; + } + + retval = op->type->invoke(C, op, event); + OPERATOR_RETVAL_CHECK(retval); + + if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { + wm->op_undo_depth--; + } + } + else if (op->type->exec) { + if (op->type->flag & OPTYPE_UNDO) { + wm->op_undo_depth++; + } + + retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + + if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { + wm->op_undo_depth--; + } + } + else { + /* debug, important to leave a while, should never happen */ + CLOG_ERROR(WM_LOG_OPERATORS, "invalid operator call '%s'", op->idname); + } + + /* Note, if the report is given as an argument then assume the caller will deal with displaying them + * currently python only uses this */ + if (!(retval & OPERATOR_HANDLED) && (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED))) { + /* only show the report if the report list was not given in the function */ + wm_operator_reports(C, op, retval, (reports != NULL)); + } + + if (retval & OPERATOR_HANDLED) { + /* do nothing, wm_operator_exec() has been called somewhere */ + } + else if (retval & OPERATOR_FINISHED) { + const bool store = !is_nested_call && use_last_properties; + wm_operator_finished(C, op, false, store); + } + else if (retval & OPERATOR_RUNNING_MODAL) { + /* take ownership of reports (in case python provided own) */ + op->reports->flag |= RPT_FREE; + + /* grab cursor during blocking modal ops (X11) + * Also check for macro + */ + if (ot->flag & OPTYPE_BLOCKING || (op->opm && op->opm->type->flag & OPTYPE_BLOCKING)) { + int bounds[4] = {-1, -1, -1, -1}; + bool wrap; + + if (event == NULL) { + wrap = false; + } + else if (op->opm) { + wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && + ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || + (op->opm->type->flag & OPTYPE_GRAB_CURSOR)); + } + else { + wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && + ((op->flag & OP_IS_MODAL_GRAB_CURSOR) || (ot->flag & OPTYPE_GRAB_CURSOR)); + } + + /* exception, cont. grab in header is annoying */ + if (wrap) { + ARegion *ar = CTX_wm_region(C); + if (ar && ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) { + wrap = false; + } + } + + if (wrap) { + const rcti *winrect = NULL; + ARegion *ar = CTX_wm_region(C); + ScrArea *sa = CTX_wm_area(C); + + if (ar && ar->regiontype == RGN_TYPE_WINDOW && + BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) { + winrect = &ar->winrct; + } + else if (sa && BLI_rcti_isect_pt_v(&sa->totrct, &event->x)) { + winrect = &sa->totrct; + } + + if (winrect) { + bounds[0] = winrect->xmin; + bounds[1] = winrect->ymax; + bounds[2] = winrect->xmax; + bounds[3] = winrect->ymin; + } + } + + WM_cursor_grab_enable(CTX_wm_window(C), wrap, false, bounds); + } + + /* cancel UI handlers, typically tooltips that can hang around + * while dragging the view or worse, that stay there permanently + * after the modal operator has swallowed all events and passed + * none to the UI handler */ + wm_handler_ui_cancel(C); + } + else { + WM_operator_free(op); + } + } + + return retval; } /** @@ -1482,161 +1512,164 @@ static int wm_operator_invoke( * * invokes operator in context */ -static int wm_operator_call_internal( - bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports, - const short context, const bool poll_only, wmEvent *event) +static int wm_operator_call_internal(bContext *C, + wmOperatorType *ot, + PointerRNA *properties, + ReportList *reports, + const short context, + const bool poll_only, + wmEvent *event) { - int retval; - - CTX_wm_operator_poll_msg_set(C, NULL); - - /* dummie test */ - if (ot) { - wmWindow *window = CTX_wm_window(C); - - if (event == NULL) { - switch (context) { - case WM_OP_INVOKE_DEFAULT: - case WM_OP_INVOKE_REGION_WIN: - case WM_OP_INVOKE_REGION_PREVIEW: - case WM_OP_INVOKE_REGION_CHANNELS: - case WM_OP_INVOKE_AREA: - case WM_OP_INVOKE_SCREEN: - /* window is needed for invoke, cancel operator */ - if (window == NULL) { - if (poll_only) { - CTX_wm_operator_poll_msg_set(C, "Missing 'window' in context"); - } - return 0; - } - else { - event = window->eventstate; - } - break; - default: - event = NULL; - break; - } - } - else { - switch (context) { - case WM_OP_EXEC_DEFAULT: - case WM_OP_EXEC_REGION_WIN: - case WM_OP_EXEC_REGION_PREVIEW: - case WM_OP_EXEC_REGION_CHANNELS: - case WM_OP_EXEC_AREA: - case WM_OP_EXEC_SCREEN: - event = NULL; - default: - break; - } - } - - switch (context) { - case WM_OP_EXEC_REGION_WIN: - case WM_OP_INVOKE_REGION_WIN: - case WM_OP_EXEC_REGION_CHANNELS: - case WM_OP_INVOKE_REGION_CHANNELS: - case WM_OP_EXEC_REGION_PREVIEW: - case WM_OP_INVOKE_REGION_PREVIEW: - { - /* forces operator to go to the region window/channels/preview, for header menus - * but we stay in the same region if we are already in one - */ - ARegion *ar = CTX_wm_region(C); - ScrArea *area = CTX_wm_area(C); - int type = RGN_TYPE_WINDOW; - - switch (context) { - case WM_OP_EXEC_REGION_CHANNELS: - case WM_OP_INVOKE_REGION_CHANNELS: - type = RGN_TYPE_CHANNELS; - break; - - case WM_OP_EXEC_REGION_PREVIEW: - case WM_OP_INVOKE_REGION_PREVIEW: - type = RGN_TYPE_PREVIEW; - break; - - case WM_OP_EXEC_REGION_WIN: - case WM_OP_INVOKE_REGION_WIN: - default: - type = RGN_TYPE_WINDOW; - break; - } - - if (!(ar && ar->regiontype == type) && area) { - ARegion *ar1; - if (type == RGN_TYPE_WINDOW) { - ar1 = BKE_area_find_region_active_win(area); - } - else { - ar1 = BKE_area_find_region_type(area, type); - } - - if (ar1) { - CTX_wm_region_set(C, ar1); - } - } - - retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true); - - /* set region back */ - CTX_wm_region_set(C, ar); - - return retval; - } - case WM_OP_EXEC_AREA: - case WM_OP_INVOKE_AREA: - { - /* remove region from context */ - ARegion *ar = CTX_wm_region(C); - - CTX_wm_region_set(C, NULL); - retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true); - CTX_wm_region_set(C, ar); - - return retval; - } - case WM_OP_EXEC_SCREEN: - case WM_OP_INVOKE_SCREEN: - { - /* remove region + area from context */ - ARegion *ar = CTX_wm_region(C); - ScrArea *area = CTX_wm_area(C); - - CTX_wm_region_set(C, NULL); - CTX_wm_area_set(C, NULL); - retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true); - CTX_wm_area_set(C, area); - CTX_wm_region_set(C, ar); - - return retval; - } - case WM_OP_EXEC_DEFAULT: - case WM_OP_INVOKE_DEFAULT: - return wm_operator_invoke(C, ot, event, properties, reports, poll_only, true); - } - } - - return 0; + int retval; + + CTX_wm_operator_poll_msg_set(C, NULL); + + /* dummie test */ + if (ot) { + wmWindow *window = CTX_wm_window(C); + + if (event == NULL) { + switch (context) { + case WM_OP_INVOKE_DEFAULT: + case WM_OP_INVOKE_REGION_WIN: + case WM_OP_INVOKE_REGION_PREVIEW: + case WM_OP_INVOKE_REGION_CHANNELS: + case WM_OP_INVOKE_AREA: + case WM_OP_INVOKE_SCREEN: + /* window is needed for invoke, cancel operator */ + if (window == NULL) { + if (poll_only) { + CTX_wm_operator_poll_msg_set(C, "Missing 'window' in context"); + } + return 0; + } + else { + event = window->eventstate; + } + break; + default: + event = NULL; + break; + } + } + else { + switch (context) { + case WM_OP_EXEC_DEFAULT: + case WM_OP_EXEC_REGION_WIN: + case WM_OP_EXEC_REGION_PREVIEW: + case WM_OP_EXEC_REGION_CHANNELS: + case WM_OP_EXEC_AREA: + case WM_OP_EXEC_SCREEN: + event = NULL; + default: + break; + } + } + + switch (context) { + case WM_OP_EXEC_REGION_WIN: + case WM_OP_INVOKE_REGION_WIN: + case WM_OP_EXEC_REGION_CHANNELS: + case WM_OP_INVOKE_REGION_CHANNELS: + case WM_OP_EXEC_REGION_PREVIEW: + case WM_OP_INVOKE_REGION_PREVIEW: { + /* forces operator to go to the region window/channels/preview, for header menus + * but we stay in the same region if we are already in one + */ + ARegion *ar = CTX_wm_region(C); + ScrArea *area = CTX_wm_area(C); + int type = RGN_TYPE_WINDOW; + + switch (context) { + case WM_OP_EXEC_REGION_CHANNELS: + case WM_OP_INVOKE_REGION_CHANNELS: + type = RGN_TYPE_CHANNELS; + break; + + case WM_OP_EXEC_REGION_PREVIEW: + case WM_OP_INVOKE_REGION_PREVIEW: + type = RGN_TYPE_PREVIEW; + break; + + case WM_OP_EXEC_REGION_WIN: + case WM_OP_INVOKE_REGION_WIN: + default: + type = RGN_TYPE_WINDOW; + break; + } + + if (!(ar && ar->regiontype == type) && area) { + ARegion *ar1; + if (type == RGN_TYPE_WINDOW) { + ar1 = BKE_area_find_region_active_win(area); + } + else { + ar1 = BKE_area_find_region_type(area, type); + } + + if (ar1) { + CTX_wm_region_set(C, ar1); + } + } + + retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true); + + /* set region back */ + CTX_wm_region_set(C, ar); + + return retval; + } + case WM_OP_EXEC_AREA: + case WM_OP_INVOKE_AREA: { + /* remove region from context */ + ARegion *ar = CTX_wm_region(C); + + CTX_wm_region_set(C, NULL); + retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true); + CTX_wm_region_set(C, ar); + + return retval; + } + case WM_OP_EXEC_SCREEN: + case WM_OP_INVOKE_SCREEN: { + /* remove region + area from context */ + ARegion *ar = CTX_wm_region(C); + ScrArea *area = CTX_wm_area(C); + + CTX_wm_region_set(C, NULL); + CTX_wm_area_set(C, NULL); + retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true); + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, ar); + + return retval; + } + case WM_OP_EXEC_DEFAULT: + case WM_OP_INVOKE_DEFAULT: + return wm_operator_invoke(C, ot, event, properties, reports, poll_only, true); + } + } + + return 0; } - /* invokes operator in context */ -int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, short context, PointerRNA *properties) +int WM_operator_name_call_ptr(bContext *C, + wmOperatorType *ot, + short context, + PointerRNA *properties) { - BLI_assert(ot == WM_operatortype_find(ot->idname, true)); - return wm_operator_call_internal(C, ot, properties, NULL, context, false, NULL); + BLI_assert(ot == WM_operatortype_find(ot->idname, true)); + return wm_operator_call_internal(C, ot, properties, NULL, context, false, NULL); } int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties) { - wmOperatorType *ot = WM_operatortype_find(opstring, 0); - if (ot) { - return WM_operator_name_call_ptr(C, ot, context, properties); - } + wmOperatorType *ot = WM_operatortype_find(opstring, 0); + if (ot) { + return WM_operator_name_call_ptr(C, ot, context, properties); + } - return 0; + return 0; } /** @@ -1644,12 +1677,12 @@ int WM_operator_name_call(bContext *C, const char *opstring, short context, Poin */ void WM_menu_name_call(bContext *C, const char *menu_name, short context) { - wmOperatorType *ot = WM_operatortype_find("WM_OT_call_menu", false); - PointerRNA ptr; - WM_operator_properties_create_ptr(&ptr, ot); - RNA_string_set(&ptr, "name", menu_name); - WM_operator_name_call_ptr(C, ot, context, &ptr); - WM_operator_properties_free(&ptr); + wmOperatorType *ot = WM_operatortype_find("WM_OT_call_menu", false); + PointerRNA ptr; + WM_operator_properties_create_ptr(&ptr, ot); + RNA_string_set(&ptr, "name", menu_name); + WM_operator_name_call_ptr(C, ot, context, &ptr); + WM_operator_properties_free(&ptr); } /** @@ -1659,197 +1692,202 @@ void WM_menu_name_call(bContext *C, const char *menu_name, short context) * - `poll()` must be called by python before this runs. * - reports can be passed to this function (so python can report them as exceptions). */ -int WM_operator_call_py( - bContext *C, wmOperatorType *ot, short context, - PointerRNA *properties, ReportList *reports, const bool is_undo) +int WM_operator_call_py(bContext *C, + wmOperatorType *ot, + short context, + PointerRNA *properties, + ReportList *reports, + const bool is_undo) { - int retval = OPERATOR_CANCELLED; + int retval = OPERATOR_CANCELLED; #if 0 - wmOperator *op; - op = wm_operator_create(wm, ot, properties, reports); + wmOperator *op; + op = wm_operator_create(wm, ot, properties, reports); - if (op->type->exec) { - if (is_undo && op->type->flag & OPTYPE_UNDO) - wm->op_undo_depth++; + if (op->type->exec) { + if (is_undo && op->type->flag & OPTYPE_UNDO) + wm->op_undo_depth++; - retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); + retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); - if (is_undo && op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) - wm->op_undo_depth--; - } - else { - CLOG_WARN(WM_LOG_OPERATORS, "\"%s\" operator has no exec function, Python cannot call it", op->type->name); - } + if (is_undo && op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) + wm->op_undo_depth--; + } + else { + CLOG_WARN(WM_LOG_OPERATORS, "\"%s\" operator has no exec function, Python cannot call it", op->type->name); + } #endif - /* not especially nice using undo depth here, its used so py never - * triggers undo or stores operators last used state. - * - * we could have some more obvious way of doing this like passing a flag. - */ - wmWindowManager *wm = CTX_wm_manager(C); - if (!is_undo && wm) { - wm->op_undo_depth++; - } + /* not especially nice using undo depth here, its used so py never + * triggers undo or stores operators last used state. + * + * we could have some more obvious way of doing this like passing a flag. + */ + wmWindowManager *wm = CTX_wm_manager(C); + if (!is_undo && wm) { + wm->op_undo_depth++; + } - retval = wm_operator_call_internal(C, ot, properties, reports, context, false, NULL); + retval = wm_operator_call_internal(C, ot, properties, reports, context, false, NULL); - if (!is_undo && wm && (wm == CTX_wm_manager(C))) { - wm->op_undo_depth--; - } + if (!is_undo && wm && (wm == CTX_wm_manager(C))) { + wm->op_undo_depth--; + } - return retval; + return retval; } - /* ********************* handlers *************** */ /* future extra customadata free? */ void wm_event_free_handler(wmEventHandler *handler) { - MEM_freeN(handler); + MEM_freeN(handler); } /* only set context when area/region is part of screen */ static void wm_handler_op_context(bContext *C, wmEventHandler_Op *handler, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - bScreen *screen = CTX_wm_screen(C); - - if (screen && handler->op) { - if (handler->context.area == NULL) { - CTX_wm_area_set(C, NULL); - } - else { - ScrArea *sa = NULL; - - ED_screen_areas_iter(win, screen, sa_iter) { - if (sa_iter == handler->context.area) { - sa = sa_iter; - break; - } - } - - if (sa == NULL) { - /* when changing screen layouts with running modal handlers (like render display), this - * is not an error to print */ - if (handler->op == NULL) { - CLOG_ERROR(WM_LOG_HANDLERS, "internal error: handler (%s) has invalid area", handler->op->type->idname); - } - } - else { - ARegion *ar; - wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL; - CTX_wm_area_set(C, sa); - - if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) { - ar = BKE_area_find_region_xy(sa, handler->context.region_type, event->x, event->y); - if (ar) { - handler->context.region = ar; - } - } - else { - ar = NULL; - } - - if (ar == NULL) { - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar == handler->context.region) { - break; - } - } - } - - /* XXX no warning print here, after full-area and back regions are remade */ - if (ar) { - CTX_wm_region_set(C, ar); - } - } - } - } + wmWindow *win = CTX_wm_window(C); + bScreen *screen = CTX_wm_screen(C); + + if (screen && handler->op) { + if (handler->context.area == NULL) { + CTX_wm_area_set(C, NULL); + } + else { + ScrArea *sa = NULL; + + ED_screen_areas_iter(win, screen, sa_iter) + { + if (sa_iter == handler->context.area) { + sa = sa_iter; + break; + } + } + + if (sa == NULL) { + /* when changing screen layouts with running modal handlers (like render display), this + * is not an error to print */ + if (handler->op == NULL) { + CLOG_ERROR(WM_LOG_HANDLERS, + "internal error: handler (%s) has invalid area", + handler->op->type->idname); + } + } + else { + ARegion *ar; + wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL; + CTX_wm_area_set(C, sa); + + if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) { + ar = BKE_area_find_region_xy(sa, handler->context.region_type, event->x, event->y); + if (ar) { + handler->context.region = ar; + } + } + else { + ar = NULL; + } + + if (ar == NULL) { + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar == handler->context.region) { + break; + } + } + } + + /* XXX no warning print here, after full-area and back regions are remade */ + if (ar) { + CTX_wm_region_set(C, ar); + } + } + } + } } /* called on exit or remove area, only here call cancel callback */ void WM_event_remove_handlers(bContext *C, ListBase *handlers) { - wmEventHandler *handler_base; - wmWindowManager *wm = CTX_wm_manager(C); - - /* C is zero on freeing database, modal handlers then already were freed */ - while ((handler_base = BLI_pophead(handlers))) { - BLI_assert(handler_base->type != 0); - if (handler_base->type == WM_HANDLER_TYPE_OP) { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - if (handler->op) { - wmWindow *win = CTX_wm_window(C); - if (handler->op->type->cancel) { - ScrArea *area = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - - wm_handler_op_context(C, handler, win->eventstate); - - if (handler->op->type->flag & OPTYPE_UNDO) { - wm->op_undo_depth++; - } - - handler->op->type->cancel(C, handler->op); - - if (handler->op->type->flag & OPTYPE_UNDO) { - wm->op_undo_depth--; - } - - CTX_wm_area_set(C, area); - CTX_wm_region_set(C, region); - } - - WM_cursor_grab_disable(win, NULL); - WM_operator_free(handler->op); - } - } - else if (handler_base->type == WM_HANDLER_TYPE_UI) { - wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; - - if (handler->remove_fn) { - ScrArea *area = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - ARegion *menu = CTX_wm_menu(C); - - if (handler->context.area) { - CTX_wm_area_set(C, handler->context.area); - } - if (handler->context.region) { - CTX_wm_region_set(C, handler->context.region); - } - if (handler->context.menu) { - CTX_wm_menu_set(C, handler->context.menu); - } - - handler->remove_fn(C, handler->user_data); - - CTX_wm_area_set(C, area); - CTX_wm_region_set(C, region); - CTX_wm_menu_set(C, menu); - } - } - - wm_event_free_handler(handler_base); - } + wmEventHandler *handler_base; + wmWindowManager *wm = CTX_wm_manager(C); + + /* C is zero on freeing database, modal handlers then already were freed */ + while ((handler_base = BLI_pophead(handlers))) { + BLI_assert(handler_base->type != 0); + if (handler_base->type == WM_HANDLER_TYPE_OP) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + if (handler->op) { + wmWindow *win = CTX_wm_window(C); + if (handler->op->type->cancel) { + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + + wm_handler_op_context(C, handler, win->eventstate); + + if (handler->op->type->flag & OPTYPE_UNDO) { + wm->op_undo_depth++; + } + + handler->op->type->cancel(C, handler->op); + + if (handler->op->type->flag & OPTYPE_UNDO) { + wm->op_undo_depth--; + } + + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + } + + WM_cursor_grab_disable(win, NULL); + WM_operator_free(handler->op); + } + } + else if (handler_base->type == WM_HANDLER_TYPE_UI) { + wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; + + if (handler->remove_fn) { + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + ARegion *menu = CTX_wm_menu(C); + + if (handler->context.area) { + CTX_wm_area_set(C, handler->context.area); + } + if (handler->context.region) { + CTX_wm_region_set(C, handler->context.region); + } + if (handler->context.menu) { + CTX_wm_menu_set(C, handler->context.menu); + } + + handler->remove_fn(C, handler->user_data); + + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + CTX_wm_menu_set(C, menu); + } + } + + wm_event_free_handler(handler_base); + } } /* do userdef mappings */ int WM_userdef_event_map(int kmitype) { - switch (kmitype) { - case WHEELOUTMOUSE: - return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE; - case WHEELINMOUSE: - return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE; - } - - return kmitype; + switch (kmitype) { + case WHEELOUTMOUSE: + return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE; + case WHEELINMOUSE: + return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE; + } + + return kmitype; } /** @@ -1859,171 +1897,169 @@ int WM_userdef_event_map(int kmitype) */ int WM_userdef_event_type_from_keymap_type(int kmitype) { - switch (kmitype) { - case EVT_TWEAK_L: - return LEFTMOUSE; - case EVT_TWEAK_M: - return MIDDLEMOUSE; - case EVT_TWEAK_R: - return RIGHTMOUSE; - case WHEELOUTMOUSE: - return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE; - case WHEELINMOUSE: - return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE; - } - - return kmitype; + switch (kmitype) { + case EVT_TWEAK_L: + return LEFTMOUSE; + case EVT_TWEAK_M: + return MIDDLEMOUSE; + case EVT_TWEAK_R: + return RIGHTMOUSE; + case WHEELOUTMOUSE: + return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE; + case WHEELINMOUSE: + return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE; + } + + return kmitype; } static bool wm_eventmatch(const wmEvent *winevent, const wmKeyMapItem *kmi) { - if (kmi->flag & KMI_INACTIVE) { - return false; - } - - const int kmitype = WM_userdef_event_map(kmi->type); - - /* the matching rules */ - if (kmitype == KM_TEXTINPUT) { - if (winevent->val == KM_PRESS) { /* prevent double clicks */ - /* NOT using ISTEXTINPUT anymore because (at least on Windows) some key codes above 255 - * could have printable ascii keys - BUG [#30479] */ - if (ISKEYBOARD(winevent->type) && (winevent->ascii || winevent->utf8_buf[0])) { - return true; - } - } - } - - if (kmitype != KM_ANY) { - if (ELEM(kmitype, TABLET_STYLUS, TABLET_ERASER)) { - const wmTabletData *wmtab = winevent->tablet_data; - - if (wmtab == NULL) { - return false; - } - else if (winevent->type != LEFTMOUSE) { - /* tablet events can occur on hover + keypress */ - return false; - } - else if ((kmitype == TABLET_STYLUS) && (wmtab->Active != EVT_TABLET_STYLUS)) { - return false; - } - else if ((kmitype == TABLET_ERASER) && (wmtab->Active != EVT_TABLET_ERASER)) { - return false; - } - } - else { - if (winevent->type != kmitype) { - return false; - } - } - } - - if (kmi->val != KM_ANY) { - if (winevent->val != kmi->val) { - return false; - } - } - - /* Modifiers also check bits, so it allows modifier order. - * Account for rare case of when these keys are used as the 'type' not as modifiers. */ - if (kmi->shift != KM_ANY) { - if ((winevent->shift != kmi->shift) && !(winevent->shift & kmi->shift) && - !ELEM(winevent->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) - { - return false; - } - } - if (kmi->ctrl != KM_ANY) { - if (winevent->ctrl != kmi->ctrl && !(winevent->ctrl & kmi->ctrl) && - !ELEM(winevent->type, LEFTCTRLKEY, RIGHTCTRLKEY)) - { - return false; - } - } - if (kmi->alt != KM_ANY) { - if (winevent->alt != kmi->alt && !(winevent->alt & kmi->alt) && - !ELEM(winevent->type, LEFTALTKEY, RIGHTALTKEY)) - { - return false; - } - } - if (kmi->oskey != KM_ANY) { - if (winevent->oskey != kmi->oskey && !(winevent->oskey & kmi->oskey) && - (winevent->type != OSKEY)) - { - return false; - } - } - - /* only keymap entry with keymodifier is checked, means all keys without modifier get handled too. */ - /* that is currently needed to make overlapping events work (when you press A - G fast or so). */ - if (kmi->keymodifier) { - if (winevent->keymodifier != kmi->keymodifier) { - return false; - } - } - - return true; + if (kmi->flag & KMI_INACTIVE) { + return false; + } + + const int kmitype = WM_userdef_event_map(kmi->type); + + /* the matching rules */ + if (kmitype == KM_TEXTINPUT) { + if (winevent->val == KM_PRESS) { /* prevent double clicks */ + /* NOT using ISTEXTINPUT anymore because (at least on Windows) some key codes above 255 + * could have printable ascii keys - BUG [#30479] */ + if (ISKEYBOARD(winevent->type) && (winevent->ascii || winevent->utf8_buf[0])) { + return true; + } + } + } + + if (kmitype != KM_ANY) { + if (ELEM(kmitype, TABLET_STYLUS, TABLET_ERASER)) { + const wmTabletData *wmtab = winevent->tablet_data; + + if (wmtab == NULL) { + return false; + } + else if (winevent->type != LEFTMOUSE) { + /* tablet events can occur on hover + keypress */ + return false; + } + else if ((kmitype == TABLET_STYLUS) && (wmtab->Active != EVT_TABLET_STYLUS)) { + return false; + } + else if ((kmitype == TABLET_ERASER) && (wmtab->Active != EVT_TABLET_ERASER)) { + return false; + } + } + else { + if (winevent->type != kmitype) { + return false; + } + } + } + + if (kmi->val != KM_ANY) { + if (winevent->val != kmi->val) { + return false; + } + } + + /* Modifiers also check bits, so it allows modifier order. + * Account for rare case of when these keys are used as the 'type' not as modifiers. */ + if (kmi->shift != KM_ANY) { + if ((winevent->shift != kmi->shift) && !(winevent->shift & kmi->shift) && + !ELEM(winevent->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) { + return false; + } + } + if (kmi->ctrl != KM_ANY) { + if (winevent->ctrl != kmi->ctrl && !(winevent->ctrl & kmi->ctrl) && + !ELEM(winevent->type, LEFTCTRLKEY, RIGHTCTRLKEY)) { + return false; + } + } + if (kmi->alt != KM_ANY) { + if (winevent->alt != kmi->alt && !(winevent->alt & kmi->alt) && + !ELEM(winevent->type, LEFTALTKEY, RIGHTALTKEY)) { + return false; + } + } + if (kmi->oskey != KM_ANY) { + if (winevent->oskey != kmi->oskey && !(winevent->oskey & kmi->oskey) && + (winevent->type != OSKEY)) { + return false; + } + } + + /* only keymap entry with keymodifier is checked, means all keys without modifier get handled too. */ + /* that is currently needed to make overlapping events work (when you press A - G fast or so). */ + if (kmi->keymodifier) { + if (winevent->keymodifier != kmi->keymodifier) { + return false; + } + } + + return true; } -static wmKeyMapItem *wm_eventmatch_modal_keymap_items(const wmKeyMap *keymap, wmOperator *op, const wmEvent *event) +static wmKeyMapItem *wm_eventmatch_modal_keymap_items(const wmKeyMap *keymap, + wmOperator *op, + const wmEvent *event) { - for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (wm_eventmatch(event, kmi)) { - if ((keymap->poll_modal_item == NULL) || - (keymap->poll_modal_item(op, kmi->propvalue))) - { - return kmi; - } - } - } - return NULL; + for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (wm_eventmatch(event, kmi)) { + if ((keymap->poll_modal_item == NULL) || (keymap->poll_modal_item(op, kmi->propvalue))) { + return kmi; + } + } + } + return NULL; } - /* operator exists */ -static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *event, bool *dbl_click_disabled) +static void wm_event_modalkeymap(const bContext *C, + wmOperator *op, + wmEvent *event, + bool *dbl_click_disabled) { - /* support for modal keymap in macros */ - if (op->opm) { - op = op->opm; - } - - if (op->type->modalkeymap) { - wmKeyMap *keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); - wmKeyMapItem *kmi = NULL; - - const wmEvent *event_match = NULL; - wmEvent event_no_dbl_click; - - if ((kmi = wm_eventmatch_modal_keymap_items(keymap, op, event))) { - event_match = event; - } - else if (event->val == KM_DBL_CLICK) { - event_no_dbl_click = *event; - event_no_dbl_click.val = KM_PRESS; - if ((kmi = wm_eventmatch_modal_keymap_items(keymap, op, &event_no_dbl_click))) { - event_match = &event_no_dbl_click; - } - } - - if (event_match != NULL) { - event->prevtype = event_match->type; - event->prevval = event_match->val; - event->type = EVT_MODAL_MAP; - event->val = kmi->propvalue; - } - } - else { - /* modal keymap checking returns handled events fine, but all hardcoded modal - * handling typically swallows all events (OPERATOR_RUNNING_MODAL). - * This bypass just disables support for double clicks in hardcoded modal handlers */ - if (event->val == KM_DBL_CLICK) { - event->val = KM_PRESS; - *dbl_click_disabled = true; - } - } + /* support for modal keymap in macros */ + if (op->opm) { + op = op->opm; + } + + if (op->type->modalkeymap) { + wmKeyMap *keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); + wmKeyMapItem *kmi = NULL; + + const wmEvent *event_match = NULL; + wmEvent event_no_dbl_click; + + if ((kmi = wm_eventmatch_modal_keymap_items(keymap, op, event))) { + event_match = event; + } + else if (event->val == KM_DBL_CLICK) { + event_no_dbl_click = *event; + event_no_dbl_click.val = KM_PRESS; + if ((kmi = wm_eventmatch_modal_keymap_items(keymap, op, &event_no_dbl_click))) { + event_match = &event_no_dbl_click; + } + } + + if (event_match != NULL) { + event->prevtype = event_match->type; + event->prevval = event_match->val; + event->type = EVT_MODAL_MAP; + event->val = kmi->propvalue; + } + } + else { + /* modal keymap checking returns handled events fine, but all hardcoded modal + * handling typically swallows all events (OPERATOR_RUNNING_MODAL). + * This bypass just disables support for double clicks in hardcoded modal handlers */ + if (event->val == KM_DBL_CLICK) { + event->val = KM_PRESS; + *dbl_click_disabled = true; + } + } } /** @@ -2032,1284 +2068,1283 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve */ static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot) { - wmWindowManager *wm = CTX_wm_manager(C); + wmWindowManager *wm = CTX_wm_manager(C); - if (wm->is_interface_locked) { - if ((ot->flag & OPTYPE_LOCK_BYPASS) == 0) { - return false; - } - } + if (wm->is_interface_locked) { + if ((ot->flag & OPTYPE_LOCK_BYPASS) == 0) { + return false; + } + } - return true; + return true; } /* bad hacking event system... better restore event type for checking of KM_CLICK for example */ /* XXX modal maps could use different method (ton) */ static void wm_event_modalmap_end(wmEvent *event, bool dbl_click_disabled) { - if (event->type == EVT_MODAL_MAP) { - event->type = event->prevtype; - event->prevtype = 0; - event->val = event->prevval; - event->prevval = 0; - } - else if (dbl_click_disabled) { - event->val = KM_DBL_CLICK; - } - + if (event->type == EVT_MODAL_MAP) { + event->type = event->prevtype; + event->prevtype = 0; + event->val = event->prevval; + event->prevval = 0; + } + else if (dbl_click_disabled) { + event->val = KM_DBL_CLICK; + } } /* Warning: this function removes a modal handler, when finished */ -static int wm_handler_operator_call( - bContext *C, ListBase *handlers, wmEventHandler *handler_base, - wmEvent *event, PointerRNA *properties) +static int wm_handler_operator_call(bContext *C, + ListBase *handlers, + wmEventHandler *handler_base, + wmEvent *event, + PointerRNA *properties) { - int retval = OPERATOR_PASS_THROUGH; - - /* derived, modal or blocking operator */ - if ((handler_base->type == WM_HANDLER_TYPE_OP) && - (((wmEventHandler_Op *)handler_base)->op != NULL)) - { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - wmOperator *op = handler->op; - wmOperatorType *ot = op->type; - - if (!wm_operator_check_locked_interface(C, ot)) { - /* Interface is locked and operator is not allowed to run, - * nothing to do in this case. - */ - } - else if (ot->modal) { - /* we set context to where modal handler came from */ - wmWindowManager *wm = CTX_wm_manager(C); - ScrArea *area = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - bool dbl_click_disabled = false; - - wm_handler_op_context(C, handler, event); - wm_region_mouse_co(C, event); - wm_event_modalkeymap(C, op, event, &dbl_click_disabled); - - if (ot->flag & OPTYPE_UNDO) { - wm->op_undo_depth++; - } - - /* warning, after this call all context data and 'event' may be freed. see check below */ - retval = ot->modal(C, op, event); - OPERATOR_RETVAL_CHECK(retval); - - /* when this is _not_ the case the modal modifier may have loaded - * a new blend file (demo mode does this), so we have to assume - * the event, operator etc have all been freed. - campbell */ - if (CTX_wm_manager(C) == wm) { - - wm_event_modalmap_end(event, dbl_click_disabled); - - if (ot->flag & OPTYPE_UNDO) { - wm->op_undo_depth--; - } - - if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { - wm_operator_reports(C, op, retval, false); - - if (op->type->modalkeymap) { - wmWindow *win = CTX_wm_window(C); - WM_window_status_area_tag_redraw(win); - } - } - else { - /* not very common, but modal operators may report before finishing */ - if (!BLI_listbase_is_empty(&op->reports->list)) { - wm_add_reports(op->reports); - } - } - - /* important to run 'wm_operator_finished' before NULLing the context members */ - if (retval & OPERATOR_FINISHED) { - wm_operator_finished(C, op, false, true); - handler->op = NULL; - } - else if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { - WM_operator_free(op); - handler->op = NULL; - } - - /* putting back screen context, reval can pass trough after modal failures! */ - if ((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) { - CTX_wm_area_set(C, area); - CTX_wm_region_set(C, region); - } - else { - /* this special cases is for areas and regions that get removed */ - CTX_wm_area_set(C, NULL); - CTX_wm_region_set(C, NULL); - } - - /* update gizmos during modal handlers */ - wm_gizmomaps_handled_modal_update(C, event, handler); - - /* remove modal handler, operator itself should have been canceled and freed */ - if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { - WM_cursor_grab_disable(CTX_wm_window(C), NULL); - - BLI_remlink(handlers, handler); - wm_event_free_handler(&handler->head); - - /* prevent silly errors from operator users */ - //retval &= ~OPERATOR_PASS_THROUGH; - } - } - } - else { - CLOG_ERROR(WM_LOG_HANDLERS, "missing modal '%s'", op->idname); - } - } - else { - wmOperatorType *ot = WM_operatortype_find(event->keymap_idname, 0); - - if (ot && wm_operator_check_locked_interface(C, ot)) { - bool use_last_properties = true; - PointerRNA tool_properties = {{0}}; - - bToolRef *keymap_tool = ( - (handler_base->type == WM_HANDLER_TYPE_KEYMAP) ? - ((wmEventHandler_Keymap *)handler_base)->keymap_tool : NULL); - const bool is_tool = (keymap_tool != NULL); - const bool use_tool_properties = is_tool; - - if (use_tool_properties) { - WM_toolsystem_ref_properties_init_for_keymap(keymap_tool, &tool_properties, properties, ot); - properties = &tool_properties; - use_last_properties = false; - } - - retval = wm_operator_invoke(C, ot, event, properties, NULL, false, use_last_properties); - - if (use_tool_properties) { - WM_operator_properties_free(&tool_properties); - } - - /* Link gizmo if 'WM_GIZMOGROUPTYPE_TOOL_INIT' is set. */ - if (retval & OPERATOR_FINISHED) { - if (is_tool) { - bToolRef_Runtime *tref_rt = keymap_tool->runtime; - if (tref_rt->gizmo_group[0]) { - const char *idname = tref_rt->gizmo_group; - wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false); - if (gzgt != NULL) { - if ((gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_INIT) != 0) { - ARegion *ar = CTX_wm_region(C); - if (ar != NULL) { - wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params); - WM_gizmo_group_type_ensure_ptr_ex(gzgt, gzmap_type); - wmGizmoGroup *gzgroup = WM_gizmomaptype_group_init_runtime_with_region(gzmap_type, gzgt, ar); - /* We can't rely on drawing to initialize gizmo's since disabling - * overlays/gizmos will prevent pre-drawing setup calls. (see T60905) */ - WM_gizmogroup_ensure_init(C, gzgroup); - } - } - } - } - } - } - /* Done linking gizmo. */ - } - } - /* Finished and pass through flag as handled */ - - /* Finished and pass through flag as handled */ - if (retval == (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH)) { - return WM_HANDLER_HANDLED; - } - - /* Modal unhandled, break */ - if (retval == (OPERATOR_PASS_THROUGH | OPERATOR_RUNNING_MODAL)) { - return (WM_HANDLER_BREAK | WM_HANDLER_MODAL); - } - - if (retval & OPERATOR_PASS_THROUGH) { - return WM_HANDLER_CONTINUE; - } - - return WM_HANDLER_BREAK; + int retval = OPERATOR_PASS_THROUGH; + + /* derived, modal or blocking operator */ + if ((handler_base->type == WM_HANDLER_TYPE_OP) && + (((wmEventHandler_Op *)handler_base)->op != NULL)) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + wmOperator *op = handler->op; + wmOperatorType *ot = op->type; + + if (!wm_operator_check_locked_interface(C, ot)) { + /* Interface is locked and operator is not allowed to run, + * nothing to do in this case. + */ + } + else if (ot->modal) { + /* we set context to where modal handler came from */ + wmWindowManager *wm = CTX_wm_manager(C); + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + bool dbl_click_disabled = false; + + wm_handler_op_context(C, handler, event); + wm_region_mouse_co(C, event); + wm_event_modalkeymap(C, op, event, &dbl_click_disabled); + + if (ot->flag & OPTYPE_UNDO) { + wm->op_undo_depth++; + } + + /* warning, after this call all context data and 'event' may be freed. see check below */ + retval = ot->modal(C, op, event); + OPERATOR_RETVAL_CHECK(retval); + + /* when this is _not_ the case the modal modifier may have loaded + * a new blend file (demo mode does this), so we have to assume + * the event, operator etc have all been freed. - campbell */ + if (CTX_wm_manager(C) == wm) { + + wm_event_modalmap_end(event, dbl_click_disabled); + + if (ot->flag & OPTYPE_UNDO) { + wm->op_undo_depth--; + } + + if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { + wm_operator_reports(C, op, retval, false); + + if (op->type->modalkeymap) { + wmWindow *win = CTX_wm_window(C); + WM_window_status_area_tag_redraw(win); + } + } + else { + /* not very common, but modal operators may report before finishing */ + if (!BLI_listbase_is_empty(&op->reports->list)) { + wm_add_reports(op->reports); + } + } + + /* important to run 'wm_operator_finished' before NULLing the context members */ + if (retval & OPERATOR_FINISHED) { + wm_operator_finished(C, op, false, true); + handler->op = NULL; + } + else if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { + WM_operator_free(op); + handler->op = NULL; + } + + /* putting back screen context, reval can pass trough after modal failures! */ + if ((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) { + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + } + else { + /* this special cases is for areas and regions that get removed */ + CTX_wm_area_set(C, NULL); + CTX_wm_region_set(C, NULL); + } + + /* update gizmos during modal handlers */ + wm_gizmomaps_handled_modal_update(C, event, handler); + + /* remove modal handler, operator itself should have been canceled and freed */ + if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { + WM_cursor_grab_disable(CTX_wm_window(C), NULL); + + BLI_remlink(handlers, handler); + wm_event_free_handler(&handler->head); + + /* prevent silly errors from operator users */ + //retval &= ~OPERATOR_PASS_THROUGH; + } + } + } + else { + CLOG_ERROR(WM_LOG_HANDLERS, "missing modal '%s'", op->idname); + } + } + else { + wmOperatorType *ot = WM_operatortype_find(event->keymap_idname, 0); + + if (ot && wm_operator_check_locked_interface(C, ot)) { + bool use_last_properties = true; + PointerRNA tool_properties = {{0}}; + + bToolRef *keymap_tool = ((handler_base->type == WM_HANDLER_TYPE_KEYMAP) ? + ((wmEventHandler_Keymap *)handler_base)->keymap_tool : + NULL); + const bool is_tool = (keymap_tool != NULL); + const bool use_tool_properties = is_tool; + + if (use_tool_properties) { + WM_toolsystem_ref_properties_init_for_keymap( + keymap_tool, &tool_properties, properties, ot); + properties = &tool_properties; + use_last_properties = false; + } + + retval = wm_operator_invoke(C, ot, event, properties, NULL, false, use_last_properties); + + if (use_tool_properties) { + WM_operator_properties_free(&tool_properties); + } + + /* Link gizmo if 'WM_GIZMOGROUPTYPE_TOOL_INIT' is set. */ + if (retval & OPERATOR_FINISHED) { + if (is_tool) { + bToolRef_Runtime *tref_rt = keymap_tool->runtime; + if (tref_rt->gizmo_group[0]) { + const char *idname = tref_rt->gizmo_group; + wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false); + if (gzgt != NULL) { + if ((gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_INIT) != 0) { + ARegion *ar = CTX_wm_region(C); + if (ar != NULL) { + wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params); + WM_gizmo_group_type_ensure_ptr_ex(gzgt, gzmap_type); + wmGizmoGroup *gzgroup = WM_gizmomaptype_group_init_runtime_with_region( + gzmap_type, gzgt, ar); + /* We can't rely on drawing to initialize gizmo's since disabling + * overlays/gizmos will prevent pre-drawing setup calls. (see T60905) */ + WM_gizmogroup_ensure_init(C, gzgroup); + } + } + } + } + } + } + /* Done linking gizmo. */ + } + } + /* Finished and pass through flag as handled */ + + /* Finished and pass through flag as handled */ + if (retval == (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH)) { + return WM_HANDLER_HANDLED; + } + + /* Modal unhandled, break */ + if (retval == (OPERATOR_PASS_THROUGH | OPERATOR_RUNNING_MODAL)) { + return (WM_HANDLER_BREAK | WM_HANDLER_MODAL); + } + + if (retval & OPERATOR_PASS_THROUGH) { + return WM_HANDLER_CONTINUE; + } + + return WM_HANDLER_BREAK; } /* fileselect handlers are only in the window queue, so it's safe to switch screens or area types */ -static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHandler_Op *handler, int val) +static int wm_handler_fileselect_do(bContext *C, + ListBase *handlers, + wmEventHandler_Op *handler, + int val) { - wmWindowManager *wm = CTX_wm_manager(C); - SpaceFile *sfile; - int action = WM_HANDLER_CONTINUE; - - switch (val) { - case EVT_FILESELECT_FULL_OPEN: - { - ScrArea *sa; - - /* sa can be null when window A is active, but mouse is over window B - * in this case, open file select in original window A. Also don't - * use global areas. */ - if (handler->context.area == NULL || ED_area_is_global(handler->context.area)) { - bScreen *screen = CTX_wm_screen(C); - sa = (ScrArea *)screen->areabase.first; - } - else { - sa = handler->context.area; - } - - if (sa->full) { - /* ensure the first area becomes the file browser, because the second one is the small - * top (info-)area which might be too small (in fullscreens we have max two areas) */ - if (sa->prev) { - sa = sa->prev; - } - ED_area_newspace(C, sa, SPACE_FILE, true); /* 'sa' is modified in-place */ - /* we already had a fullscreen here -> mark new space as a stacked fullscreen */ - sa->flag |= (AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE); - } - else if (sa->spacetype == SPACE_FILE) { - sa = ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED); - } - 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 */ - sfile = (SpaceFile *)sa->spacedata.first; - sfile->op = handler->op; - - ED_fileselect_set_params(sfile); - - action = WM_HANDLER_BREAK; - break; - } - - case EVT_FILESELECT_EXEC: - case EVT_FILESELECT_CANCEL: - case EVT_FILESELECT_EXTERNAL_CANCEL: - { - /* remlink now, for load file case before removing*/ - BLI_remlink(handlers, handler); - - if (val != EVT_FILESELECT_EXTERNAL_CANCEL) { - ScrArea *sa = CTX_wm_area(C); - - if (sa->full) { - ED_screen_full_prevspace(C, sa); - } - /* user may have left fullscreen */ - else { - ED_area_prevspace(C, sa); - } - } - - wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate); - - /* needed for UI_popup_menu_reports */ - - if (val == EVT_FILESELECT_EXEC) { - int retval; - - if (handler->op->type->flag & OPTYPE_UNDO) { - wm->op_undo_depth++; - } - - retval = handler->op->type->exec(C, handler->op); - - /* XXX check this carefully, CTX_wm_manager(C) == wm is a bit hackish */ - if (handler->op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { - wm->op_undo_depth--; - } - - /* XXX check this carefully, CTX_wm_manager(C) == wm is a bit hackish */ - if (CTX_wm_manager(C) == wm && wm->op_undo_depth == 0) { - if (handler->op->type->flag & OPTYPE_UNDO) { - ED_undo_push_op(C, handler->op); - } - else if (handler->op->type->flag & OPTYPE_UNDO_GROUPED) { - ED_undo_grouped_push_op(C, handler->op); - } - } - - if (handler->op->reports->list.first) { - - /* FIXME, temp setting window, this is really bad! - * only have because lib linking errors need to be seen by users :( - * it can be removed without breaking anything but then no linking errors - campbell */ - wmWindow *win_prev = CTX_wm_window(C); - ScrArea *area_prev = CTX_wm_area(C); - ARegion *ar_prev = CTX_wm_region(C); - - if (win_prev == NULL) { - CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); - } - - BKE_report_print_level_set(handler->op->reports, RPT_WARNING); - UI_popup_menu_reports(C, handler->op->reports); - - /* XXX - copied from 'wm_operator_finished()' */ - /* add reports to the global list, otherwise they are not seen */ - BLI_movelisttolist(&CTX_wm_reports(C)->list, &handler->op->reports->list); - - /* more hacks, since we meddle with reports, banner display doesn't happen automatic */ - WM_report_banner_show(); - - CTX_wm_window_set(C, win_prev); - CTX_wm_area_set(C, area_prev); - CTX_wm_region_set(C, ar_prev); - } - - /* for WM_operator_pystring only, custom report handling is done above */ - wm_operator_reports(C, handler->op, retval, true); - - if (retval & OPERATOR_FINISHED) { - WM_operator_last_properties_store(handler->op); - } - - if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { - WM_operator_free(handler->op); - } - } - else { - if (handler->op->type->cancel) { - if (handler->op->type->flag & OPTYPE_UNDO) { - wm->op_undo_depth++; - } - - handler->op->type->cancel(C, handler->op); + wmWindowManager *wm = CTX_wm_manager(C); + SpaceFile *sfile; + int action = WM_HANDLER_CONTINUE; + + switch (val) { + case EVT_FILESELECT_FULL_OPEN: { + ScrArea *sa; + + /* sa can be null when window A is active, but mouse is over window B + * in this case, open file select in original window A. Also don't + * use global areas. */ + if (handler->context.area == NULL || ED_area_is_global(handler->context.area)) { + bScreen *screen = CTX_wm_screen(C); + sa = (ScrArea *)screen->areabase.first; + } + else { + sa = handler->context.area; + } + + if (sa->full) { + /* ensure the first area becomes the file browser, because the second one is the small + * top (info-)area which might be too small (in fullscreens we have max two areas) */ + if (sa->prev) { + sa = sa->prev; + } + ED_area_newspace(C, sa, SPACE_FILE, true); /* 'sa' is modified in-place */ + /* we already had a fullscreen here -> mark new space as a stacked fullscreen */ + sa->flag |= (AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE); + } + else if (sa->spacetype == SPACE_FILE) { + sa = ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED); + } + 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 */ + sfile = (SpaceFile *)sa->spacedata.first; + sfile->op = handler->op; + + ED_fileselect_set_params(sfile); + + action = WM_HANDLER_BREAK; + break; + } + + case EVT_FILESELECT_EXEC: + case EVT_FILESELECT_CANCEL: + case EVT_FILESELECT_EXTERNAL_CANCEL: { + /* remlink now, for load file case before removing*/ + BLI_remlink(handlers, handler); + + if (val != EVT_FILESELECT_EXTERNAL_CANCEL) { + ScrArea *sa = CTX_wm_area(C); + + if (sa->full) { + ED_screen_full_prevspace(C, sa); + } + /* user may have left fullscreen */ + else { + ED_area_prevspace(C, sa); + } + } + + wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate); + + /* needed for UI_popup_menu_reports */ + + if (val == EVT_FILESELECT_EXEC) { + int retval; + + if (handler->op->type->flag & OPTYPE_UNDO) { + wm->op_undo_depth++; + } + + retval = handler->op->type->exec(C, handler->op); + + /* XXX check this carefully, CTX_wm_manager(C) == wm is a bit hackish */ + if (handler->op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { + wm->op_undo_depth--; + } + + /* XXX check this carefully, CTX_wm_manager(C) == wm is a bit hackish */ + if (CTX_wm_manager(C) == wm && wm->op_undo_depth == 0) { + if (handler->op->type->flag & OPTYPE_UNDO) { + ED_undo_push_op(C, handler->op); + } + else if (handler->op->type->flag & OPTYPE_UNDO_GROUPED) { + ED_undo_grouped_push_op(C, handler->op); + } + } + + if (handler->op->reports->list.first) { + + /* FIXME, temp setting window, this is really bad! + * only have because lib linking errors need to be seen by users :( + * it can be removed without breaking anything but then no linking errors - campbell */ + wmWindow *win_prev = CTX_wm_window(C); + ScrArea *area_prev = CTX_wm_area(C); + ARegion *ar_prev = CTX_wm_region(C); + + if (win_prev == NULL) { + CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); + } + + BKE_report_print_level_set(handler->op->reports, RPT_WARNING); + UI_popup_menu_reports(C, handler->op->reports); + + /* XXX - copied from 'wm_operator_finished()' */ + /* add reports to the global list, otherwise they are not seen */ + BLI_movelisttolist(&CTX_wm_reports(C)->list, &handler->op->reports->list); + + /* more hacks, since we meddle with reports, banner display doesn't happen automatic */ + WM_report_banner_show(); + + CTX_wm_window_set(C, win_prev); + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, ar_prev); + } + + /* for WM_operator_pystring only, custom report handling is done above */ + wm_operator_reports(C, handler->op, retval, true); + + if (retval & OPERATOR_FINISHED) { + WM_operator_last_properties_store(handler->op); + } + + if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { + WM_operator_free(handler->op); + } + } + else { + if (handler->op->type->cancel) { + if (handler->op->type->flag & OPTYPE_UNDO) { + wm->op_undo_depth++; + } + + handler->op->type->cancel(C, handler->op); - if (handler->op->type->flag & OPTYPE_UNDO) { - wm->op_undo_depth--; - } - } - - WM_operator_free(handler->op); - } - - CTX_wm_area_set(C, NULL); - - wm_event_free_handler(&handler->head); + if (handler->op->type->flag & OPTYPE_UNDO) { + wm->op_undo_depth--; + } + } + + WM_operator_free(handler->op); + } + + CTX_wm_area_set(C, NULL); + + wm_event_free_handler(&handler->head); - action = WM_HANDLER_BREAK; - break; - } - } - - return action; + action = WM_HANDLER_BREAK; + break; + } + } + + return action; } -static int wm_handler_fileselect_call( - bContext *C, ListBase *handlers, wmEventHandler_Op *handler, const wmEvent *event) +static int wm_handler_fileselect_call(bContext *C, + ListBase *handlers, + wmEventHandler_Op *handler, + const wmEvent *event) { - int action = WM_HANDLER_CONTINUE; + int action = WM_HANDLER_CONTINUE; - if (event->type != EVT_FILESELECT) { - return action; - } - if (handler->op != (wmOperator *)event->customdata) { - return action; - } + if (event->type != EVT_FILESELECT) { + return action; + } + if (handler->op != (wmOperator *)event->customdata) { + return action; + } - return wm_handler_fileselect_do(C, handlers, handler, event->val); + return wm_handler_fileselect_do(C, handlers, handler, event->val); } static bool handler_boundbox_test(wmEventHandler *handler, const wmEvent *event) { - if (handler->bbwin) { - if (handler->bblocal) { - rcti rect = *handler->bblocal; - BLI_rcti_translate(&rect, handler->bbwin->xmin, handler->bbwin->ymin); - - if (BLI_rcti_isect_pt_v(&rect, &event->x)) { - return 1; - } - else if (event->type == MOUSEMOVE && BLI_rcti_isect_pt_v(&rect, &event->prevx)) { - return 1; - } - else { - return 0; - } - } - else { - if (BLI_rcti_isect_pt_v(handler->bbwin, &event->x)) { - return 1; - } - else if (event->type == MOUSEMOVE && BLI_rcti_isect_pt_v(handler->bbwin, &event->prevx)) { - return 1; - } - else { - return 0; - } - } - } - return 1; + if (handler->bbwin) { + if (handler->bblocal) { + rcti rect = *handler->bblocal; + BLI_rcti_translate(&rect, handler->bbwin->xmin, handler->bbwin->ymin); + + if (BLI_rcti_isect_pt_v(&rect, &event->x)) { + return 1; + } + else if (event->type == MOUSEMOVE && BLI_rcti_isect_pt_v(&rect, &event->prevx)) { + return 1; + } + else { + return 0; + } + } + else { + if (BLI_rcti_isect_pt_v(handler->bbwin, &event->x)) { + return 1; + } + else if (event->type == MOUSEMOVE && BLI_rcti_isect_pt_v(handler->bbwin, &event->prevx)) { + return 1; + } + else { + return 0; + } + } + } + return 1; } static int wm_action_not_handled(int action) { - return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL); + return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL); } static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { - const bool do_debug_handler = (G.debug & G_DEBUG_HANDLERS) && - /* comment this out to flood the console! (if you really want to test) */ - !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) - ; -#define PRINT if (do_debug_handler) printf - - wmWindowManager *wm = CTX_wm_manager(C); - int action = WM_HANDLER_CONTINUE; - int always_pass; - - if (handlers == NULL) { - return action; - } - - /* modal handlers can get removed in this loop, we keep the loop this way - * - * note: check 'handlers->first' because in rare cases the handlers can be cleared - * by the event that's called, for eg: - * - * Calling a python script which changes the area.type, see [#32232] */ - for (wmEventHandler *handler_base = handlers->first, *handler_base_next; - handler_base && handlers->first; - handler_base = handler_base_next) - { - handler_base_next = handler_base->next; - - /* during this loop, ui handlers for nested menus can tag multiple handlers free */ - if (handler_base->flag & WM_HANDLER_DO_FREE) { - /* pass */ - } - else if (handler_boundbox_test(handler_base, event)) { /* optional boundbox */ - /* in advance to avoid access to freed event on window close */ - always_pass = wm_event_always_pass(event); - - /* modal+blocking handler_base */ - if (handler_base->flag & WM_HANDLER_BLOCKING) { - action |= WM_HANDLER_BREAK; - } - - /* Handle all types here. */ - if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { - wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - - PRINT("%s: checking '%s' ...", __func__, keymap->idname); - - if (keymap == NULL) { - /* Only callback is allowed to have NULL keymaps. */ - BLI_assert(handler->dynamic.keymap_fn); - } - else if (WM_keymap_poll(C, keymap)) { - - PRINT("pass\n"); - - for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (wm_eventmatch(event, kmi)) { - struct wmEventHandler_KeymapPost keymap_post = handler->post; - - PRINT("%s: item matched '%s'\n", __func__, kmi->idname); - - /* weak, but allows interactive callback to not use rawkey */ - event->keymap_idname = kmi->idname; - - action |= wm_handler_operator_call(C, handlers, handler_base, event, kmi->ptr); - - if (action & WM_HANDLER_BREAK) { - /* not always_pass here, it denotes removed handler_base */ - CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname); - if (keymap_post.post_fn != NULL) { - keymap_post.post_fn(keymap, kmi, keymap_post.user_data); - } - break; - } - else { - if (action & WM_HANDLER_HANDLED) { - CLOG_INFO(WM_LOG_HANDLERS, 2, "handled - and pass on! '%s'", kmi->idname); - } - else { - CLOG_INFO(WM_LOG_HANDLERS, 2, "un-handled '%s'", kmi->idname); - } - } - } - } - } - else { - PRINT("fail\n"); - } - } - else if (handler_base->type == WM_HANDLER_TYPE_UI) { - wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; - BLI_assert(handler->handle_fn != NULL); - if (!wm->is_interface_locked) { - action |= wm_handler_ui_call(C, handler, event, always_pass); - } - } - else if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) { - wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base; - if (!wm->is_interface_locked && event->type == EVT_DROP) { - wmDropBox *drop = handler->dropboxes->first; - for (; drop; drop = drop->next) { - /* other drop custom types allowed */ - if (event->custom == EVT_DATA_DRAGDROP) { - ListBase *lb = (ListBase *)event->customdata; - wmDrag *drag; - - for (drag = lb->first; drag; drag = drag->next) { - const char *tooltip = NULL; - if (drop->poll(C, drag, event, &tooltip)) { - /* Optionally copy drag information to operator properties. */ - if (drop->copy) { - drop->copy(drag, drop); - } - - /* Pass single matched wmDrag onto the operator. */ - BLI_remlink(lb, drag); - ListBase single_lb = {drag, drag}; - event->customdata = &single_lb; - - wm_operator_call_internal(C, drop->ot, drop->ptr, NULL, drop->opcontext, false, event); - action |= WM_HANDLER_BREAK; - - /* free the drags */ - WM_drag_free_list(lb); - WM_drag_free_list(&single_lb); - - event->customdata = NULL; - event->custom = 0; - - /* XXX fileread case */ - if (CTX_wm_window(C) == NULL) { - return action; - } - - /* escape from drag loop, got freed */ - break; - } - } - } - } - } - } - else if (handler_base->type == WM_HANDLER_TYPE_GIZMO) { - wmEventHandler_Gizmo *handler = (wmEventHandler_Gizmo *)handler_base; - ScrArea *area = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - wmGizmoMap *gzmap = handler->gizmo_map; - BLI_assert(gzmap != NULL); - wmGizmo *gz = wm_gizmomap_highlight_get(gzmap); - - if (region->gizmo_map != handler->gizmo_map) { - WM_gizmomap_tag_refresh(handler->gizmo_map); - } - - wm_gizmomap_handler_context_gizmo(C, handler); - wm_region_mouse_co(C, event); - - /* handle gizmo highlighting */ - if (event->type == MOUSEMOVE && !wm_gizmomap_modal_get(gzmap)) { - int part; - gz = wm_gizmomap_highlight_find(gzmap, C, event, &part); - if (wm_gizmomap_highlight_set(gzmap, C, gz, part) && gz != NULL) { - if (U.flag & USER_TOOLTIPS) { - WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_gizmomap_tooltip_init); - } - } - } - else { - /* Either we operate on a single highlighted item - * or groups attached to the selected gizmos. - * To simplify things both cases loop over an array of items. */ - wmGizmoGroup *gzgroup_first; - bool is_gzgroup_single; - - if (ISMOUSE(event->type)) { - /* Keep gz set as-is, just fake single selection. */ - if (gz) { - gzgroup_first = gz->parent_gzgroup; - } - else { - gzgroup_first = NULL; - } - is_gzgroup_single = true; - } - else { - if (WM_gizmomap_is_any_selected(gzmap)) { - const ListBase *groups = WM_gizmomap_group_list(gzmap); - gzgroup_first = groups->first; - } - else { - gzgroup_first = NULL; - } - is_gzgroup_single = false; - } - - /* Don't use from now on. */ - gz = NULL; - - for (wmGizmoGroup *gzgroup = gzgroup_first; gzgroup; gzgroup = gzgroup->next) { - /* get user customized keymap from default one */ - - if ((is_gzgroup_single == false) && - /* We might want to change the logic here and use some kind of gizmo edit-mode. - * For now just use keymap when a selection exists. */ - wm_gizmogroup_is_any_selected(gzgroup) == false) - { - continue; - } - - wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap); - wmKeyMapItem *kmi; - - PRINT("%s: checking '%s' ...", __func__, keymap->idname); - - if (WM_keymap_poll(C, keymap)) { - PRINT("pass\n"); - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (wm_eventmatch(event, kmi)) { - PRINT("%s: item matched '%s'\n", __func__, kmi->idname); - - /* weak, but allows interactive callback to not use rawkey */ - event->keymap_idname = kmi->idname; - - CTX_wm_gizmo_group_set(C, gzgroup); - - /* handler->op is called later, we want keymap op to be triggered here */ - action |= wm_handler_operator_call(C, handlers, handler_base, event, kmi->ptr); - - CTX_wm_gizmo_group_set(C, NULL); - - if (action & WM_HANDLER_BREAK) { - if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) { - printf("%s: handled - and pass on! '%s'\n", - __func__, kmi->idname); - } - break; - } - else { - if (action & WM_HANDLER_HANDLED) { - if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) { - printf("%s: handled - and pass on! '%s'\n", - __func__, kmi->idname); - } - } - else { - PRINT("%s: un-handled '%s'\n", - __func__, kmi->idname); - } - } - } - } - } - else { - PRINT("fail\n"); - } - - if (action & WM_HANDLER_BREAK) { - break; - } - - if (is_gzgroup_single) { - break; - } - } - } - - /* restore the area */ - CTX_wm_area_set(C, area); - CTX_wm_region_set(C, region); - } - else if (handler_base->type == WM_HANDLER_TYPE_OP) { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - if (handler->is_fileselect) { - if (!wm->is_interface_locked) { - /* screen context changes here */ - action |= wm_handler_fileselect_call(C, handlers, handler, event); - } - } - else { - action |= wm_handler_operator_call(C, handlers, handler_base, event, NULL); - } - } - else { - /* Unreachable (handle all types above). */ - BLI_assert(0); - } - - if (action & WM_HANDLER_BREAK) { - if (always_pass) { - action &= ~WM_HANDLER_BREAK; - } - else { - break; - } - } - } - - /* XXX fileread case, if the wm is freed then the handler's - * will have been too so the code below need not run. */ - if (CTX_wm_window(C) == NULL) { - return action; - } - - /* XXX code this for all modal ops, and ensure free only happens here */ - - /* modal ui handler can be tagged to be freed */ - if (BLI_findindex(handlers, handler_base) != -1) { /* could be freed already by regular modal ops */ - if (handler_base->flag & WM_HANDLER_DO_FREE) { - BLI_remlink(handlers, handler_base); - wm_event_free_handler(handler_base); - } - } - } - - if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL)) { - wm_cursor_arrow_move(CTX_wm_window(C), event); - } + const bool do_debug_handler = + (G.debug & G_DEBUG_HANDLERS) && + /* comment this out to flood the console! (if you really want to test) */ + !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE); +#define PRINT \ + if (do_debug_handler) \ + printf + + wmWindowManager *wm = CTX_wm_manager(C); + int action = WM_HANDLER_CONTINUE; + int always_pass; + + if (handlers == NULL) { + return action; + } + + /* modal handlers can get removed in this loop, we keep the loop this way + * + * note: check 'handlers->first' because in rare cases the handlers can be cleared + * by the event that's called, for eg: + * + * Calling a python script which changes the area.type, see [#32232] */ + for (wmEventHandler *handler_base = handlers->first, *handler_base_next; + handler_base && handlers->first; + handler_base = handler_base_next) { + handler_base_next = handler_base->next; + + /* during this loop, ui handlers for nested menus can tag multiple handlers free */ + if (handler_base->flag & WM_HANDLER_DO_FREE) { + /* pass */ + } + else if (handler_boundbox_test(handler_base, event)) { /* optional boundbox */ + /* in advance to avoid access to freed event on window close */ + always_pass = wm_event_always_pass(event); + + /* modal+blocking handler_base */ + if (handler_base->flag & WM_HANDLER_BLOCKING) { + action |= WM_HANDLER_BREAK; + } + + /* Handle all types here. */ + if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { + wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; + wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); + + PRINT("%s: checking '%s' ...", __func__, keymap->idname); + + if (keymap == NULL) { + /* Only callback is allowed to have NULL keymaps. */ + BLI_assert(handler->dynamic.keymap_fn); + } + else if (WM_keymap_poll(C, keymap)) { + + PRINT("pass\n"); + + for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (wm_eventmatch(event, kmi)) { + struct wmEventHandler_KeymapPost keymap_post = handler->post; + + PRINT("%s: item matched '%s'\n", __func__, kmi->idname); + + /* weak, but allows interactive callback to not use rawkey */ + event->keymap_idname = kmi->idname; + + action |= wm_handler_operator_call(C, handlers, handler_base, event, kmi->ptr); + + if (action & WM_HANDLER_BREAK) { + /* not always_pass here, it denotes removed handler_base */ + CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname); + if (keymap_post.post_fn != NULL) { + keymap_post.post_fn(keymap, kmi, keymap_post.user_data); + } + break; + } + else { + if (action & WM_HANDLER_HANDLED) { + CLOG_INFO(WM_LOG_HANDLERS, 2, "handled - and pass on! '%s'", kmi->idname); + } + else { + CLOG_INFO(WM_LOG_HANDLERS, 2, "un-handled '%s'", kmi->idname); + } + } + } + } + } + else { + PRINT("fail\n"); + } + } + else if (handler_base->type == WM_HANDLER_TYPE_UI) { + wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; + BLI_assert(handler->handle_fn != NULL); + if (!wm->is_interface_locked) { + action |= wm_handler_ui_call(C, handler, event, always_pass); + } + } + else if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) { + wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base; + if (!wm->is_interface_locked && event->type == EVT_DROP) { + wmDropBox *drop = handler->dropboxes->first; + for (; drop; drop = drop->next) { + /* other drop custom types allowed */ + if (event->custom == EVT_DATA_DRAGDROP) { + ListBase *lb = (ListBase *)event->customdata; + wmDrag *drag; + + for (drag = lb->first; drag; drag = drag->next) { + const char *tooltip = NULL; + if (drop->poll(C, drag, event, &tooltip)) { + /* Optionally copy drag information to operator properties. */ + if (drop->copy) { + drop->copy(drag, drop); + } + + /* Pass single matched wmDrag onto the operator. */ + BLI_remlink(lb, drag); + ListBase single_lb = {drag, drag}; + event->customdata = &single_lb; + + wm_operator_call_internal( + C, drop->ot, drop->ptr, NULL, drop->opcontext, false, event); + action |= WM_HANDLER_BREAK; + + /* free the drags */ + WM_drag_free_list(lb); + WM_drag_free_list(&single_lb); + + event->customdata = NULL; + event->custom = 0; + + /* XXX fileread case */ + if (CTX_wm_window(C) == NULL) { + return action; + } + + /* escape from drag loop, got freed */ + break; + } + } + } + } + } + } + else if (handler_base->type == WM_HANDLER_TYPE_GIZMO) { + wmEventHandler_Gizmo *handler = (wmEventHandler_Gizmo *)handler_base; + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + wmGizmoMap *gzmap = handler->gizmo_map; + BLI_assert(gzmap != NULL); + wmGizmo *gz = wm_gizmomap_highlight_get(gzmap); + + if (region->gizmo_map != handler->gizmo_map) { + WM_gizmomap_tag_refresh(handler->gizmo_map); + } + + wm_gizmomap_handler_context_gizmo(C, handler); + wm_region_mouse_co(C, event); + + /* handle gizmo highlighting */ + if (event->type == MOUSEMOVE && !wm_gizmomap_modal_get(gzmap)) { + int part; + gz = wm_gizmomap_highlight_find(gzmap, C, event, &part); + if (wm_gizmomap_highlight_set(gzmap, C, gz, part) && gz != NULL) { + if (U.flag & USER_TOOLTIPS) { + WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_gizmomap_tooltip_init); + } + } + } + else { + /* Either we operate on a single highlighted item + * or groups attached to the selected gizmos. + * To simplify things both cases loop over an array of items. */ + wmGizmoGroup *gzgroup_first; + bool is_gzgroup_single; + + if (ISMOUSE(event->type)) { + /* Keep gz set as-is, just fake single selection. */ + if (gz) { + gzgroup_first = gz->parent_gzgroup; + } + else { + gzgroup_first = NULL; + } + is_gzgroup_single = true; + } + else { + if (WM_gizmomap_is_any_selected(gzmap)) { + const ListBase *groups = WM_gizmomap_group_list(gzmap); + gzgroup_first = groups->first; + } + else { + gzgroup_first = NULL; + } + is_gzgroup_single = false; + } + + /* Don't use from now on. */ + gz = NULL; + + for (wmGizmoGroup *gzgroup = gzgroup_first; gzgroup; gzgroup = gzgroup->next) { + /* get user customized keymap from default one */ + + if ((is_gzgroup_single == false) && + /* We might want to change the logic here and use some kind of gizmo edit-mode. + * For now just use keymap when a selection exists. */ + wm_gizmogroup_is_any_selected(gzgroup) == false) { + continue; + } + + wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap); + wmKeyMapItem *kmi; + + PRINT("%s: checking '%s' ...", __func__, keymap->idname); + + if (WM_keymap_poll(C, keymap)) { + PRINT("pass\n"); + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (wm_eventmatch(event, kmi)) { + PRINT("%s: item matched '%s'\n", __func__, kmi->idname); + + /* weak, but allows interactive callback to not use rawkey */ + event->keymap_idname = kmi->idname; + + CTX_wm_gizmo_group_set(C, gzgroup); + + /* handler->op is called later, we want keymap op to be triggered here */ + action |= wm_handler_operator_call(C, handlers, handler_base, event, kmi->ptr); + + CTX_wm_gizmo_group_set(C, NULL); + + if (action & WM_HANDLER_BREAK) { + if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) { + printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname); + } + break; + } + else { + if (action & WM_HANDLER_HANDLED) { + if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) { + printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname); + } + } + else { + PRINT("%s: un-handled '%s'\n", __func__, kmi->idname); + } + } + } + } + } + else { + PRINT("fail\n"); + } + + if (action & WM_HANDLER_BREAK) { + break; + } + + if (is_gzgroup_single) { + break; + } + } + } + + /* restore the area */ + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + } + else if (handler_base->type == WM_HANDLER_TYPE_OP) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + if (handler->is_fileselect) { + if (!wm->is_interface_locked) { + /* screen context changes here */ + action |= wm_handler_fileselect_call(C, handlers, handler, event); + } + } + else { + action |= wm_handler_operator_call(C, handlers, handler_base, event, NULL); + } + } + else { + /* Unreachable (handle all types above). */ + BLI_assert(0); + } + + if (action & WM_HANDLER_BREAK) { + if (always_pass) { + action &= ~WM_HANDLER_BREAK; + } + else { + break; + } + } + } + + /* XXX fileread case, if the wm is freed then the handler's + * will have been too so the code below need not run. */ + if (CTX_wm_window(C) == NULL) { + return action; + } + + /* XXX code this for all modal ops, and ensure free only happens here */ + + /* modal ui handler can be tagged to be freed */ + if (BLI_findindex(handlers, handler_base) != + -1) { /* could be freed already by regular modal ops */ + if (handler_base->flag & WM_HANDLER_DO_FREE) { + BLI_remlink(handlers, handler_base); + wm_event_free_handler(handler_base); + } + } + } + + if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL)) { + wm_cursor_arrow_move(CTX_wm_window(C), event); + } #undef PRINT - return action; + return action; } /* this calls handlers twice - to solve (double-)click events */ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) { - int action = wm_handlers_do_intern(C, event, handlers); - - /* fileread case */ - if (CTX_wm_window(C) == NULL) { - return action; - } - - if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - - /* Test for CLICK_DRAG events. */ - if (wm_action_not_handled(action)) { - if (event->check_drag) { - wmWindow *win = CTX_wm_window(C); - if ((abs(event->x - win->eventstate->prevclickx)) >= WM_EVENT_CURSOR_CLICK_DRAG_THRESHOLD || - (abs(event->y - win->eventstate->prevclicky)) >= WM_EVENT_CURSOR_CLICK_DRAG_THRESHOLD) - { - int x = event->x; - int y = event->y; - short val = event->val; - short type = event->type; - - event->x = win->eventstate->prevclickx; - event->y = win->eventstate->prevclicky; - event->val = KM_CLICK_DRAG; - event->type = win->eventstate->type; - - CLOG_INFO(WM_LOG_HANDLERS, 1, "handling PRESS_DRAG"); - - action |= wm_handlers_do_intern(C, event, handlers); - - event->val = val; - event->type = type; - event->x = x; - event->y = y; - - win->eventstate->check_click = false; - win->eventstate->check_drag = false; - } - } - } - else { - wmWindow *win = CTX_wm_window(C); - if (win) { - win->eventstate->check_drag = false; - } - } - } - else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) { - /* All events that don't set wmEvent.prevtype must be ignored. */ - - /* Test for CLICK events. */ - if (wm_action_not_handled(action)) { - wmWindow *win = CTX_wm_window(C); - - /* eventstate stores if previous event was a KM_PRESS, in case that - * wasn't handled, the KM_RELEASE will become a KM_CLICK */ - - if (win != NULL) { - if (event->val == KM_PRESS) { - win->eventstate->check_click = true; - win->eventstate->check_drag = true; - } - else if (event->val == KM_RELEASE) { - win->eventstate->check_drag = false; - } - } - - if (win && win->eventstate->prevtype == event->type) { - - if ((event->val == KM_RELEASE) && - (win->eventstate->prevval == KM_PRESS) && - (win->eventstate->check_click == true)) - { - if ((abs(event->x - win->eventstate->prevclickx)) < WM_EVENT_CLICK_TWEAK_THRESHOLD && - (abs(event->y - win->eventstate->prevclicky)) < WM_EVENT_CLICK_TWEAK_THRESHOLD) - { - /* Position is where the actual click happens, for more - * accurate selecting in case the mouse drifts a little. */ - int x = event->x; - int y = event->y; - - event->x = win->eventstate->prevclickx; - event->y = win->eventstate->prevclicky; - event->val = KM_CLICK; - - CLOG_INFO(WM_LOG_HANDLERS, 1, "handling CLICK"); - - action |= wm_handlers_do_intern(C, event, handlers); - - event->val = KM_RELEASE; - event->x = x; - event->y = y; - } - else { - win->eventstate->check_click = 0; - win->eventstate->check_drag = 0; - } - } - else if (event->val == KM_DBL_CLICK) { - /* The underlying event is a press, so try and handle this. */ - event->val = KM_PRESS; - action |= wm_handlers_do_intern(C, event, handlers); - - /* revert value if not handled */ - if (wm_action_not_handled(action)) { - event->val = KM_DBL_CLICK; - } - } - } - } - else { - wmWindow *win = CTX_wm_window(C); - if (win) { - win->eventstate->check_click = 0; - } - } - } - - return action; + int action = wm_handlers_do_intern(C, event, handlers); + + /* fileread case */ + if (CTX_wm_window(C) == NULL) { + return action; + } + + if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + + /* Test for CLICK_DRAG events. */ + if (wm_action_not_handled(action)) { + if (event->check_drag) { + wmWindow *win = CTX_wm_window(C); + if ((abs(event->x - win->eventstate->prevclickx)) >= + WM_EVENT_CURSOR_CLICK_DRAG_THRESHOLD || + (abs(event->y - win->eventstate->prevclicky)) >= + WM_EVENT_CURSOR_CLICK_DRAG_THRESHOLD) { + int x = event->x; + int y = event->y; + short val = event->val; + short type = event->type; + + event->x = win->eventstate->prevclickx; + event->y = win->eventstate->prevclicky; + event->val = KM_CLICK_DRAG; + event->type = win->eventstate->type; + + CLOG_INFO(WM_LOG_HANDLERS, 1, "handling PRESS_DRAG"); + + action |= wm_handlers_do_intern(C, event, handlers); + + event->val = val; + event->type = type; + event->x = x; + event->y = y; + + win->eventstate->check_click = false; + win->eventstate->check_drag = false; + } + } + } + else { + wmWindow *win = CTX_wm_window(C); + if (win) { + win->eventstate->check_drag = false; + } + } + } + else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) { + /* All events that don't set wmEvent.prevtype must be ignored. */ + + /* Test for CLICK events. */ + if (wm_action_not_handled(action)) { + wmWindow *win = CTX_wm_window(C); + + /* eventstate stores if previous event was a KM_PRESS, in case that + * wasn't handled, the KM_RELEASE will become a KM_CLICK */ + + if (win != NULL) { + if (event->val == KM_PRESS) { + win->eventstate->check_click = true; + win->eventstate->check_drag = true; + } + else if (event->val == KM_RELEASE) { + win->eventstate->check_drag = false; + } + } + + if (win && win->eventstate->prevtype == event->type) { + + if ((event->val == KM_RELEASE) && (win->eventstate->prevval == KM_PRESS) && + (win->eventstate->check_click == true)) { + if ((abs(event->x - win->eventstate->prevclickx)) < WM_EVENT_CLICK_TWEAK_THRESHOLD && + (abs(event->y - win->eventstate->prevclicky)) < WM_EVENT_CLICK_TWEAK_THRESHOLD) { + /* Position is where the actual click happens, for more + * accurate selecting in case the mouse drifts a little. */ + int x = event->x; + int y = event->y; + + event->x = win->eventstate->prevclickx; + event->y = win->eventstate->prevclicky; + event->val = KM_CLICK; + + CLOG_INFO(WM_LOG_HANDLERS, 1, "handling CLICK"); + + action |= wm_handlers_do_intern(C, event, handlers); + + event->val = KM_RELEASE; + event->x = x; + event->y = y; + } + else { + win->eventstate->check_click = 0; + win->eventstate->check_drag = 0; + } + } + else if (event->val == KM_DBL_CLICK) { + /* The underlying event is a press, so try and handle this. */ + event->val = KM_PRESS; + action |= wm_handlers_do_intern(C, event, handlers); + + /* revert value if not handled */ + if (wm_action_not_handled(action)) { + event->val = KM_DBL_CLICK; + } + } + } + } + else { + wmWindow *win = CTX_wm_window(C); + if (win) { + win->eventstate->check_click = 0; + } + } + } + + return action; } static int wm_event_inside_i(wmEvent *event, rcti *rect) { - if (wm_event_always_pass(event)) { - return 1; - } - if (BLI_rcti_isect_pt_v(rect, &event->x)) { - return 1; - } - return 0; + if (wm_event_always_pass(event)) { + return 1; + } + if (BLI_rcti_isect_pt_v(rect, &event->x)) { + return 1; + } + return 0; } static ScrArea *area_event_inside(bContext *C, const int xy[2]) { - wmWindow *win = CTX_wm_window(C); - bScreen *screen = CTX_wm_screen(C); - - if (screen) { - ED_screen_areas_iter(win, screen, sa) { - if (BLI_rcti_isect_pt_v(&sa->totrct, xy)) { - return sa; - } - } - } - return NULL; + wmWindow *win = CTX_wm_window(C); + bScreen *screen = CTX_wm_screen(C); + + if (screen) { + ED_screen_areas_iter(win, screen, sa) + { + if (BLI_rcti_isect_pt_v(&sa->totrct, xy)) { + return sa; + } + } + } + return NULL; } static ARegion *region_event_inside(bContext *C, const int xy[2]) { - bScreen *screen = CTX_wm_screen(C); - ScrArea *area = CTX_wm_area(C); - ARegion *ar; - - if (screen && area) { - for (ar = area->regionbase.first; ar; ar = ar->next) { - if (BLI_rcti_isect_pt_v(&ar->winrct, xy)) { - return ar; - } - } - } - return NULL; + bScreen *screen = CTX_wm_screen(C); + ScrArea *area = CTX_wm_area(C); + ARegion *ar; + + if (screen && area) { + for (ar = area->regionbase.first; ar; ar = ar->next) { + if (BLI_rcti_isect_pt_v(&ar->winrct, xy)) { + return ar; + } + } + } + return NULL; } static void wm_paintcursor_tag(bContext *C, wmPaintCursor *pc, ARegion *ar) { - if (ar) { - for (; pc; pc = pc->next) { - if (pc->poll == NULL || pc->poll(C)) { - wmWindow *win = CTX_wm_window(C); - WM_paint_cursor_tag_redraw(win, ar); - } - } - } + if (ar) { + for (; pc; pc = pc->next) { + if (pc->poll == NULL || pc->poll(C)) { + wmWindow *win = CTX_wm_window(C); + WM_paint_cursor_tag_redraw(win, ar); + } + } + } } /* called on mousemove, check updates for paintcursors */ /* context was set on active area and region */ static void wm_paintcursor_test(bContext *C, const wmEvent *event) { - wmWindowManager *wm = CTX_wm_manager(C); + wmWindowManager *wm = CTX_wm_manager(C); - if (wm->paintcursors.first) { - ARegion *ar = CTX_wm_region(C); + if (wm->paintcursors.first) { + ARegion *ar = CTX_wm_region(C); - if (ar) { - wm_paintcursor_tag(C, wm->paintcursors.first, ar); - } + if (ar) { + wm_paintcursor_tag(C, wm->paintcursors.first, ar); + } - /* if previous position was not in current region, we have to set a temp new context */ - if (ar == NULL || !BLI_rcti_isect_pt_v(&ar->winrct, &event->prevx)) { - ScrArea *sa = CTX_wm_area(C); + /* if previous position was not in current region, we have to set a temp new context */ + if (ar == NULL || !BLI_rcti_isect_pt_v(&ar->winrct, &event->prevx)) { + ScrArea *sa = CTX_wm_area(C); - CTX_wm_area_set(C, area_event_inside(C, &event->prevx)); - CTX_wm_region_set(C, region_event_inside(C, &event->prevx)); + CTX_wm_area_set(C, area_event_inside(C, &event->prevx)); + CTX_wm_region_set(C, region_event_inside(C, &event->prevx)); - wm_paintcursor_tag(C, wm->paintcursors.first, CTX_wm_region(C)); + wm_paintcursor_tag(C, wm->paintcursors.first, CTX_wm_region(C)); - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); - } - } + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + } + } } static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *event) { - bScreen *screen = WM_window_get_active_screen(win); - - if (BLI_listbase_is_empty(&wm->drags)) { - return; - } - - if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) { - screen->do_draw_drag = true; - } - else if (event->type == ESCKEY) { - WM_drag_free_list(&wm->drags); - - screen->do_draw_drag = true; - } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { - event->type = EVT_DROP; - - /* create customdata, first free existing */ - if (event->customdata) { - if (event->customdatafree) { - MEM_freeN(event->customdata); - } - } - - event->custom = EVT_DATA_DRAGDROP; - event->customdata = &wm->drags; - event->customdatafree = 1; - - /* clear drop icon */ - screen->do_draw_drag = true; - - /* restore cursor (disabled, see wm_dragdrop.c) */ - // WM_cursor_modal_restore(win); - } + bScreen *screen = WM_window_get_active_screen(win); + + if (BLI_listbase_is_empty(&wm->drags)) { + return; + } + + if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) { + screen->do_draw_drag = true; + } + else if (event->type == ESCKEY) { + WM_drag_free_list(&wm->drags); + + screen->do_draw_drag = true; + } + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + event->type = EVT_DROP; + + /* create customdata, first free existing */ + if (event->customdata) { + if (event->customdatafree) { + MEM_freeN(event->customdata); + } + } + + event->custom = EVT_DATA_DRAGDROP; + event->customdata = &wm->drags; + event->customdatafree = 1; + + /* clear drop icon */ + screen->do_draw_drag = true; + + /* restore cursor (disabled, see wm_dragdrop.c) */ + // WM_cursor_modal_restore(win); + } } /* filter out all events of the pie that spawned the last pie unless it's a release event */ static bool wm_event_pie_filter(wmWindow *win, const wmEvent *event) { - if (win->lock_pie_event && win->lock_pie_event == event->type) { - if (event->val == KM_RELEASE) { - win->lock_pie_event = EVENT_NONE; - return false; - } - else { - return true; - } - } - else { - return false; - } + if (win->lock_pie_event && win->lock_pie_event == event->type) { + if (event->val == KM_RELEASE) { + win->lock_pie_event = EVENT_NONE; + return false; + } + else { + return true; + } + } + else { + return false; + } } /* called in main loop */ /* goes over entire hierarchy: events -> window -> screen -> area -> region */ void wm_event_do_handlers(bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win; - - /* update key configuration before handling events */ - WM_keyconfig_update(wm); - WM_gizmoconfig_update(CTX_data_main(C)); - - for (win = wm->windows.first; win; win = win->next) { - bScreen *screen = WM_window_get_active_screen(win); - wmEvent *event; - - /* some safety checks - these should always be set! */ - BLI_assert(WM_window_get_active_scene(win)); - BLI_assert(WM_window_get_active_screen(win)); - BLI_assert(WM_window_get_active_workspace(win)); - - if (screen == NULL) { - wm_event_free_all(win); - } - else { - Scene *scene = WM_window_get_active_scene(win); - - if (scene) { - int is_playing_sound = BKE_sound_scene_playing(scene); - - if (is_playing_sound != -1) { - bool is_playing_screen; - CTX_wm_window_set(C, win); - CTX_data_scene_set(C, scene); - - is_playing_screen = (ED_screen_animation_playing(wm) != NULL); - - if (((is_playing_sound == 1) && (is_playing_screen == 0)) || - ((is_playing_sound == 0) && (is_playing_screen == 1))) - { - ED_screen_animation_play(C, -1, 1); - } - - if (is_playing_sound == 0) { - const float time = BKE_sound_sync_scene(scene); - if (isfinite(time)) { - int ncfra = time * (float)FPS + 0.5f; - if (ncfra != scene->r.cfra) { - scene->r.cfra = ncfra; - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ED_update_for_newframe(CTX_data_main(C), depsgraph); - WM_event_add_notifier(C, NC_WINDOW, NULL); - } - } - } - - CTX_data_scene_set(C, NULL); - CTX_wm_screen_set(C, NULL); - CTX_wm_window_set(C, NULL); - } - } - } - - while ( (event = win->queue.first) ) { - int action = WM_HANDLER_CONTINUE; - - /* active screen might change during handlers, update pointer */ - screen = WM_window_get_active_screen(win); - - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - printf("\n%s: Handling event\n", __func__); - WM_event_print(event); - } - - /* take care of pie event filter */ - if (wm_event_pie_filter(win, event)) { - if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - CLOG_INFO(WM_LOG_HANDLERS, 1, "event filtered due to pie button pressed"); - } - BLI_remlink(&win->queue, event); - wm_event_free(event); - continue; - } - - CTX_wm_window_set(C, win); - - /* Clear tool-tip on mouse move. */ - if (screen->tool_tip && screen->tool_tip->exit_on_event) { - if (ISMOUSE(event->type)) { - WM_tooltip_clear(C, win); - } - } - - /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ - CTX_wm_area_set(C, area_event_inside(C, &event->x)); - CTX_wm_region_set(C, region_event_inside(C, &event->x)); - - /* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */ - wm_window_make_drawable(wm, win); - - wm_region_mouse_co(C, event); - - - /* first we do priority handlers, modal + some limited keymaps */ - action |= wm_handlers_do(C, event, &win->modalhandlers); - - /* fileread case */ - if (CTX_wm_window(C) == NULL) { - return; - } - - /* check for a tooltip */ - if (screen == WM_window_get_active_screen(win)) { - if (screen->tool_tip && screen->tool_tip->timer) { - if ((event->type == TIMER) && (event->customdata == screen->tool_tip->timer)) { - WM_tooltip_init(C, win); - } - } - } - - /* check dragging, creates new event or frees, adds draw tag */ - wm_event_drag_test(wm, win, event); - - /* builtin tweak, if action is break it removes tweak */ - wm_tweakevent_test(C, event, action); - - if ((action & WM_HANDLER_BREAK) == 0) { - ARegion *ar; - - /* Note: setting subwin active should be done here, after modal handlers have been done */ - if (event->type == MOUSEMOVE) { - /* state variables in screen, cursors. Also used in wm_draw.c, fails for modal handlers though */ - ED_screen_set_active_region(C, win, &event->x); - /* for regions having custom cursors */ - wm_paintcursor_test(C, event); - } + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win; + + /* update key configuration before handling events */ + WM_keyconfig_update(wm); + WM_gizmoconfig_update(CTX_data_main(C)); + + for (win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); + wmEvent *event; + + /* some safety checks - these should always be set! */ + BLI_assert(WM_window_get_active_scene(win)); + BLI_assert(WM_window_get_active_screen(win)); + BLI_assert(WM_window_get_active_workspace(win)); + + if (screen == NULL) { + wm_event_free_all(win); + } + else { + Scene *scene = WM_window_get_active_scene(win); + + if (scene) { + int is_playing_sound = BKE_sound_scene_playing(scene); + + if (is_playing_sound != -1) { + bool is_playing_screen; + CTX_wm_window_set(C, win); + CTX_data_scene_set(C, scene); + + is_playing_screen = (ED_screen_animation_playing(wm) != NULL); + + if (((is_playing_sound == 1) && (is_playing_screen == 0)) || + ((is_playing_sound == 0) && (is_playing_screen == 1))) { + ED_screen_animation_play(C, -1, 1); + } + + if (is_playing_sound == 0) { + const float time = BKE_sound_sync_scene(scene); + if (isfinite(time)) { + int ncfra = time * (float)FPS + 0.5f; + if (ncfra != scene->r.cfra) { + scene->r.cfra = ncfra; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ED_update_for_newframe(CTX_data_main(C), depsgraph); + WM_event_add_notifier(C, NC_WINDOW, NULL); + } + } + } + + CTX_data_scene_set(C, NULL); + CTX_wm_screen_set(C, NULL); + CTX_wm_window_set(C, NULL); + } + } + } + + while ((event = win->queue.first)) { + int action = WM_HANDLER_CONTINUE; + + /* active screen might change during handlers, update pointer */ + screen = WM_window_get_active_screen(win); + + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && + !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + printf("\n%s: Handling event\n", __func__); + WM_event_print(event); + } + + /* take care of pie event filter */ + if (wm_event_pie_filter(win, event)) { + if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + CLOG_INFO(WM_LOG_HANDLERS, 1, "event filtered due to pie button pressed"); + } + BLI_remlink(&win->queue, event); + wm_event_free(event); + continue; + } + + CTX_wm_window_set(C, win); + + /* Clear tool-tip on mouse move. */ + if (screen->tool_tip && screen->tool_tip->exit_on_event) { + if (ISMOUSE(event->type)) { + WM_tooltip_clear(C, win); + } + } + + /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ + CTX_wm_area_set(C, area_event_inside(C, &event->x)); + CTX_wm_region_set(C, region_event_inside(C, &event->x)); + + /* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */ + wm_window_make_drawable(wm, win); + + wm_region_mouse_co(C, event); + + /* first we do priority handlers, modal + some limited keymaps */ + action |= wm_handlers_do(C, event, &win->modalhandlers); + + /* fileread case */ + if (CTX_wm_window(C) == NULL) { + return; + } + + /* check for a tooltip */ + if (screen == WM_window_get_active_screen(win)) { + if (screen->tool_tip && screen->tool_tip->timer) { + if ((event->type == TIMER) && (event->customdata == screen->tool_tip->timer)) { + WM_tooltip_init(C, win); + } + } + } + + /* check dragging, creates new event or frees, adds draw tag */ + wm_event_drag_test(wm, win, event); + + /* builtin tweak, if action is break it removes tweak */ + wm_tweakevent_test(C, event, action); + + if ((action & WM_HANDLER_BREAK) == 0) { + ARegion *ar; + + /* Note: setting subwin active should be done here, after modal handlers have been done */ + if (event->type == MOUSEMOVE) { + /* state variables in screen, cursors. Also used in wm_draw.c, fails for modal handlers though */ + ED_screen_set_active_region(C, win, &event->x); + /* for regions having custom cursors */ + wm_paintcursor_test(C, event); + } #ifdef WITH_INPUT_NDOF - else if (event->type == NDOF_MOTION) { - win->addmousemove = true; - } + else if (event->type == NDOF_MOTION) { + win->addmousemove = true; + } #endif - ED_screen_areas_iter(win, screen, sa) { - /* after restoring a screen from SCREENMAXIMIZED we have to wait - * with the screen handling till the region coordinates are updated */ - if (screen->skip_handling == true) { - /* restore for the next iteration of wm_event_do_handlers */ - screen->skip_handling = false; - break; - } - - /* update azones if needed - done here because it needs to be independent from redraws */ - if (sa->flag & AREA_FLAG_ACTIONZONES_UPDATE) { - ED_area_azones_update(sa, &event->x); - } - - if (wm_event_inside_i(event, &sa->totrct)) { - CTX_wm_area_set(C, sa); - - if ((action & WM_HANDLER_BREAK) == 0) { - for (ar = sa->regionbase.first; ar; ar = ar->next) { - 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); - - if (!BLI_listbase_is_empty(&wm->drags)) { - /* 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) || ISKEYMODIFIER(event->type)) { - wm_drags_check_ops(C, event); - } - } - - action |= wm_handlers_do(C, event, &ar->handlers); - - /* fileread case (python), [#29489] */ - if (CTX_wm_window(C) == NULL) { - return; - } - - if (action & WM_HANDLER_BREAK) { - break; - } - } - } - } - - CTX_wm_region_set(C, NULL); - - 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 */ - } - } - - if ((action & WM_HANDLER_BREAK) == 0) { - /* also some non-modal handlers need active area/region */ - CTX_wm_area_set(C, area_event_inside(C, &event->x)); - CTX_wm_region_set(C, region_event_inside(C, &event->x)); - - wm_region_mouse_co(C, event); - - action |= wm_handlers_do(C, event, &win->handlers); - - /* fileread case */ - if (CTX_wm_window(C) == NULL) { - return; - } - } - - } - - /* If press was handled, we don't want to do click. This way - * press in tool keymap can override click in editor keymap.*/ - if (ISMOUSE_BUTTON(event->type) && - event->val == KM_PRESS && - !wm_action_not_handled(action)) - { - win->eventstate->check_click = false; - } - - /* update previous mouse position for following events to use */ - win->eventstate->prevx = event->x; - win->eventstate->prevy = event->y; - - /* unlink and free here, blender-quit then frees all */ - BLI_remlink(&win->queue, event); - wm_event_free(event); - - } - - /* only add mousemove when queue was read entirely */ - if (win->addmousemove && win->eventstate) { - wmEvent tevent = *(win->eventstate); - // printf("adding MOUSEMOVE %d %d\n", tevent.x, tevent.y); - tevent.type = MOUSEMOVE; - tevent.prevx = tevent.x; - tevent.prevy = tevent.y; - wm_event_add(win, &tevent); - win->addmousemove = 0; - } - - CTX_wm_window_set(C, NULL); - } - - /* update key configuration after handling events */ - WM_keyconfig_update(wm); - WM_gizmoconfig_update(CTX_data_main(C)); + ED_screen_areas_iter(win, screen, sa) + { + /* after restoring a screen from SCREENMAXIMIZED we have to wait + * with the screen handling till the region coordinates are updated */ + if (screen->skip_handling == true) { + /* restore for the next iteration of wm_event_do_handlers */ + screen->skip_handling = false; + break; + } + + /* update azones if needed - done here because it needs to be independent from redraws */ + if (sa->flag & AREA_FLAG_ACTIONZONES_UPDATE) { + ED_area_azones_update(sa, &event->x); + } + + if (wm_event_inside_i(event, &sa->totrct)) { + CTX_wm_area_set(C, sa); + + if ((action & WM_HANDLER_BREAK) == 0) { + for (ar = sa->regionbase.first; ar; ar = ar->next) { + 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); + + if (!BLI_listbase_is_empty(&wm->drags)) { + /* 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) || ISKEYMODIFIER(event->type)) { + wm_drags_check_ops(C, event); + } + } + + action |= wm_handlers_do(C, event, &ar->handlers); + + /* fileread case (python), [#29489] */ + if (CTX_wm_window(C) == NULL) { + return; + } + + if (action & WM_HANDLER_BREAK) { + break; + } + } + } + } + + CTX_wm_region_set(C, NULL); + + 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 */ + } + } + + if ((action & WM_HANDLER_BREAK) == 0) { + /* also some non-modal handlers need active area/region */ + CTX_wm_area_set(C, area_event_inside(C, &event->x)); + CTX_wm_region_set(C, region_event_inside(C, &event->x)); + + wm_region_mouse_co(C, event); + + action |= wm_handlers_do(C, event, &win->handlers); + + /* fileread case */ + if (CTX_wm_window(C) == NULL) { + return; + } + } + } + + /* If press was handled, we don't want to do click. This way + * press in tool keymap can override click in editor keymap.*/ + if (ISMOUSE_BUTTON(event->type) && event->val == KM_PRESS && + !wm_action_not_handled(action)) { + win->eventstate->check_click = false; + } + + /* update previous mouse position for following events to use */ + win->eventstate->prevx = event->x; + win->eventstate->prevy = event->y; + + /* unlink and free here, blender-quit then frees all */ + BLI_remlink(&win->queue, event); + wm_event_free(event); + } + + /* only add mousemove when queue was read entirely */ + if (win->addmousemove && win->eventstate) { + wmEvent tevent = *(win->eventstate); + // printf("adding MOUSEMOVE %d %d\n", tevent.x, tevent.y); + tevent.type = MOUSEMOVE; + tevent.prevx = tevent.x; + tevent.prevy = tevent.y; + wm_event_add(win, &tevent); + win->addmousemove = 0; + } + + CTX_wm_window_set(C, NULL); + } + + /* update key configuration after handling events */ + WM_keyconfig_update(wm); + WM_gizmoconfig_update(CTX_data_main(C)); } /* ********** filesector handling ************ */ void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval) { - /* add to all windows! */ - wmWindow *win; + /* add to all windows! */ + wmWindow *win; - for (win = wm->windows.first; win; win = win->next) { - wmEvent event = *win->eventstate; + for (win = wm->windows.first; win; win = win->next) { + wmEvent event = *win->eventstate; - event.type = EVT_FILESELECT; - event.val = eventval; - event.customdata = ophandle; // only as void pointer type check + event.type = EVT_FILESELECT; + event.val = eventval; + event.customdata = ophandle; // only as void pointer type check - wm_event_add(win, &event); - } + wm_event_add(win, &event); + } } /* operator is supposed to have a filled "path" property */ @@ -3323,98 +3358,101 @@ void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval */ void WM_event_add_fileselect(bContext *C, wmOperator *op) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - - /* Close any popups, like when opening a file browser from the splash. */ - UI_popup_handlers_remove_all(C, &win->modalhandlers); - - /* only allow 1 file selector open per window */ - LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, &win->modalhandlers) { - if (handler_base->type == WM_HANDLER_TYPE_OP) { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - if (handler->is_fileselect == false) { - continue; - } - bScreen *screen = CTX_wm_screen(C); - bool cancel_handler = true; - - /* find the area with the file selector for this handler */ - ED_screen_areas_iter(win, screen, sa) { - if (sa->spacetype == SPACE_FILE) { - SpaceFile *sfile = sa->spacedata.first; - - if (sfile->op == handler->op) { - CTX_wm_area_set(C, sa); - wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_CANCEL); - cancel_handler = false; - break; - } - } - } - - /* if not found we stop the handler without changing the screen */ - if (cancel_handler) { - wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_EXTERNAL_CANCEL); - } - } - } - - wmEventHandler_Op *handler = MEM_callocN(sizeof(*handler), __func__); - handler->head.type = WM_HANDLER_TYPE_OP; - - handler->is_fileselect = true; - handler->op = op; - handler->context.area = CTX_wm_area(C); - handler->context.region = CTX_wm_region(C); - - BLI_addhead(&win->modalhandlers, handler); - - /* check props once before invoking if check is available - * ensures initial properties are valid */ - if (op->type->check) { - op->type->check(C, op); /* ignore return value */ - } - - WM_event_fileselect_event(wm, op, EVT_FILESELECT_FULL_OPEN); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + + /* Close any popups, like when opening a file browser from the splash. */ + UI_popup_handlers_remove_all(C, &win->modalhandlers); + + /* only allow 1 file selector open per window */ + LISTBASE_FOREACH_MUTABLE(wmEventHandler *, handler_base, &win->modalhandlers) + { + if (handler_base->type == WM_HANDLER_TYPE_OP) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + if (handler->is_fileselect == false) { + continue; + } + bScreen *screen = CTX_wm_screen(C); + bool cancel_handler = true; + + /* find the area with the file selector for this handler */ + ED_screen_areas_iter(win, screen, sa) + { + if (sa->spacetype == SPACE_FILE) { + SpaceFile *sfile = sa->spacedata.first; + + if (sfile->op == handler->op) { + CTX_wm_area_set(C, sa); + wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_CANCEL); + cancel_handler = false; + break; + } + } + } + + /* if not found we stop the handler without changing the screen */ + if (cancel_handler) { + wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_EXTERNAL_CANCEL); + } + } + } + + wmEventHandler_Op *handler = MEM_callocN(sizeof(*handler), __func__); + handler->head.type = WM_HANDLER_TYPE_OP; + + handler->is_fileselect = true; + handler->op = op; + handler->context.area = CTX_wm_area(C); + handler->context.region = CTX_wm_region(C); + + BLI_addhead(&win->modalhandlers, handler); + + /* check props once before invoking if check is available + * ensures initial properties are valid */ + if (op->type->check) { + op->type->check(C, op); /* ignore return value */ + } + + WM_event_fileselect_event(wm, op, EVT_FILESELECT_FULL_OPEN); } #if 0 /* lets not expose struct outside wm? */ static void WM_event_set_handler_flag(wmEventHandler *handler, int flag) { - handler->flag = flag; + handler->flag = flag; } #endif wmEventHandler_Op *WM_event_add_modal_handler(bContext *C, wmOperator *op) { - wmEventHandler_Op *handler = MEM_callocN(sizeof(*handler), __func__); - handler->head.type = WM_HANDLER_TYPE_OP; - wmWindow *win = CTX_wm_window(C); - - /* operator was part of macro */ - if (op->opm) { - /* give the mother macro to the handler */ - handler->op = op->opm; - /* mother macro opm becomes the macro element */ - handler->op->opm = op; - } - else { - handler->op = op; - } - - handler->context.area = CTX_wm_area(C); /* means frozen screen context for modal handlers! */ - handler->context.region = CTX_wm_region(C); - handler->context.region_type = handler->context.region ? handler->context.region->regiontype : -1; - - BLI_addhead(&win->modalhandlers, handler); - - if (op->type->modalkeymap) { - WM_window_status_area_tag_redraw(win); - } - - return handler; + wmEventHandler_Op *handler = MEM_callocN(sizeof(*handler), __func__); + handler->head.type = WM_HANDLER_TYPE_OP; + wmWindow *win = CTX_wm_window(C); + + /* operator was part of macro */ + if (op->opm) { + /* give the mother macro to the handler */ + handler->op = op->opm; + /* mother macro opm becomes the macro element */ + handler->op->opm = op; + } + else { + handler->op = op; + } + + handler->context.area = CTX_wm_area(C); /* means frozen screen context for modal handlers! */ + handler->context.region = CTX_wm_region(C); + handler->context.region_type = handler->context.region ? handler->context.region->regiontype : + -1; + + BLI_addhead(&win->modalhandlers, handler); + + if (op->type->modalkeymap) { + WM_window_status_area_tag_redraw(win); + } + + return handler; } /** @@ -3423,1131 +3461,1201 @@ wmEventHandler_Op *WM_event_add_modal_handler(bContext *C, wmOperator *op) */ void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area) { - LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { - if (handler_base->type == WM_HANDLER_TYPE_OP) { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - /* fileselect handler is quite special... it needs to keep old area stored in handler, so don't change it */ - if ((handler->context.area == old_area) && (handler->is_fileselect == false)) { - handler->context.area = new_area; - } - } - } + LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { + if (handler_base->type == WM_HANDLER_TYPE_OP) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + /* fileselect handler is quite special... it needs to keep old area stored in handler, so don't change it */ + if ((handler->context.area == old_area) && (handler->is_fileselect == false)) { + handler->context.area = new_area; + } + } + } } /** * Modal handlers store a pointer to a region which might be freed while the handler runs. * Use this function to NULL all handler pointers to \a old_region. */ -void WM_event_modal_handler_region_replace(wmWindow *win, const ARegion *old_region, ARegion *new_region) +void WM_event_modal_handler_region_replace(wmWindow *win, + const ARegion *old_region, + ARegion *new_region) { - LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { - if (handler_base->type == WM_HANDLER_TYPE_OP) { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - /* fileselect handler is quite special... it needs to keep old region stored in handler, so don't change it */ - if ((handler->context.region == old_region) && (handler->is_fileselect == false)) { - handler->context.region = new_region; - handler->context.region_type = new_region ? new_region->regiontype : RGN_TYPE_WINDOW; - } - } - } + LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { + if (handler_base->type == WM_HANDLER_TYPE_OP) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + /* fileselect handler is quite special... it needs to keep old region stored in handler, so don't change it */ + if ((handler->context.region == old_region) && (handler->is_fileselect == false)) { + handler->context.region = new_region; + handler->context.region_type = new_region ? new_region->regiontype : RGN_TYPE_WINDOW; + } + } + } } wmEventHandler_Keymap *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap) { - if (!keymap) { - CLOG_WARN(WM_LOG_HANDLERS, "called with NULL keymap"); - return NULL; - } - - /* only allow same keymap once */ - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { - wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - if (handler->keymap == keymap) { - return handler; - } - } - } - - wmEventHandler_Keymap *handler = MEM_callocN(sizeof(*handler), __func__); - handler->head.type = WM_HANDLER_TYPE_KEYMAP; - BLI_addtail(handlers, handler); - handler->keymap = keymap; - - return handler; + if (!keymap) { + CLOG_WARN(WM_LOG_HANDLERS, "called with NULL keymap"); + return NULL; + } + + /* only allow same keymap once */ + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { + if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { + wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; + if (handler->keymap == keymap) { + return handler; + } + } + } + + wmEventHandler_Keymap *handler = MEM_callocN(sizeof(*handler), __func__); + handler->head.type = WM_HANDLER_TYPE_KEYMAP; + BLI_addtail(handlers, handler); + handler->keymap = keymap; + + return handler; } /** Follow #wmEventHandler_KeymapDynamicFn signiture. */ wmKeyMap *WM_event_get_keymap_from_toolsystem(wmWindowManager *wm, wmEventHandler_Keymap *handler) { - ScrArea *sa = handler->dynamic.user_data; - handler->keymap_tool = NULL; - bToolRef_Runtime *tref_rt = sa->runtime.tool ? sa->runtime.tool->runtime : NULL; - if (tref_rt && tref_rt->keymap[0]) { - wmKeyMap *km = WM_keymap_list_find_spaceid_or_empty( - &wm->userconf->keymaps, tref_rt->keymap, sa->spacetype, RGN_TYPE_WINDOW); - /* We shouldn't use keymaps from unrelated spaces. */ - if (km != NULL) { - handler->keymap_tool = sa->runtime.tool; - return km; - } - else { - printf("Keymap: '%s' not found for tool '%s'\n", tref_rt->keymap, sa->runtime.tool->idname); - } - } - return NULL; + ScrArea *sa = handler->dynamic.user_data; + handler->keymap_tool = NULL; + bToolRef_Runtime *tref_rt = sa->runtime.tool ? sa->runtime.tool->runtime : NULL; + if (tref_rt && tref_rt->keymap[0]) { + wmKeyMap *km = WM_keymap_list_find_spaceid_or_empty( + &wm->userconf->keymaps, tref_rt->keymap, sa->spacetype, RGN_TYPE_WINDOW); + /* We shouldn't use keymaps from unrelated spaces. */ + if (km != NULL) { + handler->keymap_tool = sa->runtime.tool; + return km; + } + else { + printf("Keymap: '%s' not found for tool '%s'\n", tref_rt->keymap, sa->runtime.tool->idname); + } + } + return NULL; } struct wmEventHandler_Keymap *WM_event_add_keymap_handler_dynamic( - ListBase *handlers, wmEventHandler_KeymapDynamicFn *keymap_fn, void *user_data) + ListBase *handlers, wmEventHandler_KeymapDynamicFn *keymap_fn, void *user_data) { - if (!keymap_fn) { - CLOG_WARN(WM_LOG_HANDLERS, "called with NULL keymap_fn"); - return NULL; - } - - /* only allow same keymap once */ - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { - wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - if (handler->dynamic.keymap_fn == keymap_fn) { - /* Maximizing the view needs to update the area. */ - handler->dynamic.user_data = user_data; - return handler; - } - } - } - - wmEventHandler_Keymap *handler = MEM_callocN(sizeof(*handler), __func__); - handler->head.type = WM_HANDLER_TYPE_KEYMAP; - BLI_addtail(handlers, handler); - handler->dynamic.keymap_fn = keymap_fn; - handler->dynamic.user_data = user_data; - - return handler; + if (!keymap_fn) { + CLOG_WARN(WM_LOG_HANDLERS, "called with NULL keymap_fn"); + return NULL; + } + + /* only allow same keymap once */ + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { + if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { + wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; + if (handler->dynamic.keymap_fn == keymap_fn) { + /* Maximizing the view needs to update the area. */ + handler->dynamic.user_data = user_data; + return handler; + } + } + } + + wmEventHandler_Keymap *handler = MEM_callocN(sizeof(*handler), __func__); + handler->head.type = WM_HANDLER_TYPE_KEYMAP; + BLI_addtail(handlers, handler); + handler->dynamic.keymap_fn = keymap_fn; + handler->dynamic.user_data = user_data; + + return handler; } /* priorities not implemented yet, for time being just insert in begin of list */ -wmEventHandler_Keymap *WM_event_add_keymap_handler_priority(ListBase *handlers, wmKeyMap *keymap, int UNUSED(priority)) +wmEventHandler_Keymap *WM_event_add_keymap_handler_priority(ListBase *handlers, + wmKeyMap *keymap, + int UNUSED(priority)) { - WM_event_remove_keymap_handler(handlers, keymap); + WM_event_remove_keymap_handler(handlers, keymap); - wmEventHandler_Keymap *handler = MEM_callocN(sizeof(*handler), "event keymap handler"); - handler->head.type = WM_HANDLER_TYPE_KEYMAP; + wmEventHandler_Keymap *handler = MEM_callocN(sizeof(*handler), "event keymap handler"); + handler->head.type = WM_HANDLER_TYPE_KEYMAP; - BLI_addhead(handlers, handler); - handler->keymap = keymap; + BLI_addhead(handlers, handler); + handler->keymap = keymap; - return handler; + return handler; } -wmEventHandler_Keymap *WM_event_add_keymap_handler_bb(ListBase *handlers, wmKeyMap *keymap, const rcti *bblocal, const rcti *bbwin) +wmEventHandler_Keymap *WM_event_add_keymap_handler_bb(ListBase *handlers, + wmKeyMap *keymap, + const rcti *bblocal, + const rcti *bbwin) { - wmEventHandler_Keymap *handler = WM_event_add_keymap_handler(handlers, keymap); + wmEventHandler_Keymap *handler = WM_event_add_keymap_handler(handlers, keymap); - if (handler) { - handler->head.bblocal = bblocal; - handler->head.bbwin = bbwin; - } - return handler; + if (handler) { + handler->head.bblocal = bblocal; + handler->head.bbwin = bbwin; + } + return handler; } void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap) { - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { - wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - if (handler->keymap == keymap) { - BLI_remlink(handlers, handler); - wm_event_free_handler(&handler->head); - break; - } - } - } + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { + if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { + wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; + if (handler->keymap == keymap) { + BLI_remlink(handlers, handler); + wm_event_free_handler(&handler->head); + break; + } + } + } } -void WM_event_set_keymap_handler_post_callback( - wmEventHandler_Keymap *handler, - void (keymap_tag)(wmKeyMap *keymap, wmKeyMapItem *kmi, void *user_data), - void *user_data) +void WM_event_set_keymap_handler_post_callback(wmEventHandler_Keymap *handler, + void(keymap_tag)(wmKeyMap *keymap, + wmKeyMapItem *kmi, + void *user_data), + void *user_data) { - handler->post.post_fn = keymap_tag; - handler->post.user_data = user_data; + handler->post.post_fn = keymap_tag; + handler->post.user_data = user_data; } -wmEventHandler_UI *WM_event_add_ui_handler( - const bContext *C, ListBase *handlers, - wmUIHandlerFunc handle_fn, wmUIHandlerRemoveFunc remove_fn, - void *user_data, const char flag) +wmEventHandler_UI *WM_event_add_ui_handler(const bContext *C, + ListBase *handlers, + wmUIHandlerFunc handle_fn, + wmUIHandlerRemoveFunc remove_fn, + void *user_data, + const char flag) { - wmEventHandler_UI *handler = MEM_callocN(sizeof(*handler), __func__); - handler->head.type = WM_HANDLER_TYPE_UI; - handler->handle_fn = handle_fn; - handler->remove_fn = remove_fn; - handler->user_data = user_data; - if (C) { - handler->context.area = CTX_wm_area(C); - handler->context.region = CTX_wm_region(C); - handler->context.menu = CTX_wm_menu(C); - } - else { - handler->context.area = NULL; - handler->context.region = NULL; - handler->context.menu = NULL; - } - - BLI_assert((flag & WM_HANDLER_DO_FREE) == 0); - handler->head.flag = flag; - - BLI_addhead(handlers, handler); - - return handler; + wmEventHandler_UI *handler = MEM_callocN(sizeof(*handler), __func__); + handler->head.type = WM_HANDLER_TYPE_UI; + handler->handle_fn = handle_fn; + handler->remove_fn = remove_fn; + handler->user_data = user_data; + if (C) { + handler->context.area = CTX_wm_area(C); + handler->context.region = CTX_wm_region(C); + handler->context.menu = CTX_wm_menu(C); + } + else { + handler->context.area = NULL; + handler->context.region = NULL; + handler->context.menu = NULL; + } + + BLI_assert((flag & WM_HANDLER_DO_FREE) == 0); + handler->head.flag = flag; + + BLI_addhead(handlers, handler); + + return handler; } /* set "postpone" for win->modalhandlers, this is in a running for () loop in wm_handlers_do() */ -void WM_event_remove_ui_handler( - ListBase *handlers, - wmUIHandlerFunc handle_fn, wmUIHandlerRemoveFunc remove_fn, - void *user_data, const bool postpone) +void WM_event_remove_ui_handler(ListBase *handlers, + wmUIHandlerFunc handle_fn, + wmUIHandlerRemoveFunc remove_fn, + void *user_data, + const bool postpone) { - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_UI) { - wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; - if ((handler->handle_fn == handle_fn) && - (handler->remove_fn == remove_fn) && - (handler->user_data == user_data)) - { - /* handlers will be freed in wm_handlers_do() */ - if (postpone) { - handler->head.flag |= WM_HANDLER_DO_FREE; - } - else { - BLI_remlink(handlers, handler); - wm_event_free_handler(&handler->head); - } - break; - } - } - } + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { + if (handler_base->type == WM_HANDLER_TYPE_UI) { + wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; + if ((handler->handle_fn == handle_fn) && (handler->remove_fn == remove_fn) && + (handler->user_data == user_data)) { + /* handlers will be freed in wm_handlers_do() */ + if (postpone) { + handler->head.flag |= WM_HANDLER_DO_FREE; + } + else { + BLI_remlink(handlers, handler); + wm_event_free_handler(&handler->head); + } + break; + } + } + } } -void WM_event_free_ui_handler_all( - bContext *C, ListBase *handlers, - wmUIHandlerFunc handle_fn, wmUIHandlerRemoveFunc remove_fn) +void WM_event_free_ui_handler_all(bContext *C, + ListBase *handlers, + wmUIHandlerFunc handle_fn, + wmUIHandlerRemoveFunc remove_fn) { - LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_UI) { - wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; - if ((handler->handle_fn == handle_fn) && - (handler->remove_fn == remove_fn)) - { - remove_fn(C, handler->user_data); - BLI_remlink(handlers, handler); - wm_event_free_handler(&handler->head); - } - } - } + LISTBASE_FOREACH_MUTABLE(wmEventHandler *, handler_base, handlers) + { + if (handler_base->type == WM_HANDLER_TYPE_UI) { + wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; + if ((handler->handle_fn == handle_fn) && (handler->remove_fn == remove_fn)) { + remove_fn(C, handler->user_data); + BLI_remlink(handlers, handler); + wm_event_free_handler(&handler->head); + } + } + } } wmEventHandler_Dropbox *WM_event_add_dropbox_handler(ListBase *handlers, ListBase *dropboxes) { - /* only allow same dropbox once */ - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) { - wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base; - if (handler->dropboxes == dropboxes) { - return handler; - } - } - } - - wmEventHandler_Dropbox *handler = MEM_callocN(sizeof(*handler), __func__); - handler->head.type = WM_HANDLER_TYPE_DROPBOX; - - /* dropbox stored static, no free or copy */ - handler->dropboxes = dropboxes; - BLI_addhead(handlers, handler); - - return handler; + /* only allow same dropbox once */ + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { + if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) { + wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base; + if (handler->dropboxes == dropboxes) { + return handler; + } + } + } + + wmEventHandler_Dropbox *handler = MEM_callocN(sizeof(*handler), __func__); + handler->head.type = WM_HANDLER_TYPE_DROPBOX; + + /* dropbox stored static, no free or copy */ + handler->dropboxes = dropboxes; + BLI_addhead(handlers, handler); + + return handler; } /* XXX solution works, still better check the real cause (ton) */ void WM_event_remove_area_handler(ListBase *handlers, void *area) { - LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_UI) { - wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; - if (handler->context.area == area) { - BLI_remlink(handlers, handler); - wm_event_free_handler(handler_base); - } - } - } + LISTBASE_FOREACH_MUTABLE(wmEventHandler *, handler_base, handlers) + { + if (handler_base->type == WM_HANDLER_TYPE_UI) { + wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; + if (handler->context.area == area) { + BLI_remlink(handlers, handler); + wm_event_free_handler(handler_base); + } + } + } } #if 0 static void WM_event_remove_handler(ListBase *handlers, wmEventHandler *handler) { - BLI_remlink(handlers, handler); - wm_event_free_handler(handler); + BLI_remlink(handlers, handler); + wm_event_free_handler(handler); } #endif void WM_event_add_mousemove(const bContext *C) { - wmWindow *window = CTX_wm_window(C); + wmWindow *window = CTX_wm_window(C); - window->addmousemove = 1; + window->addmousemove = 1; } - /* for modal callbacks, check configuration for how to interpret exit with tweaks */ bool WM_event_is_modal_tweak_exit(const wmEvent *event, int tweak_event) { - /* if the release-confirm userpref setting is enabled, - * tweak events can be canceled when mouse is released - */ - if (U.flag & USER_RELEASECONFIRM) { - /* option on, so can exit with km-release */ - if (event->val == KM_RELEASE) { - switch (tweak_event) { - case EVT_TWEAK_L: - case EVT_TWEAK_M: - case EVT_TWEAK_R: - return 1; - } - } - else { - /* if the initial event wasn't a tweak event then - * ignore USER_RELEASECONFIRM setting: see [#26756] */ - if (ELEM(tweak_event, EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R) == 0) { - return 1; - } - } - } - else { - /* this is fine as long as not doing km-release, otherwise - * some items (i.e. markers) being tweaked may end up getting - * dropped all over - */ - if (event->val != KM_RELEASE) { - return 1; - } - } - - return 0; + /* if the release-confirm userpref setting is enabled, + * tweak events can be canceled when mouse is released + */ + if (U.flag & USER_RELEASECONFIRM) { + /* option on, so can exit with km-release */ + if (event->val == KM_RELEASE) { + switch (tweak_event) { + case EVT_TWEAK_L: + case EVT_TWEAK_M: + case EVT_TWEAK_R: + return 1; + } + } + else { + /* if the initial event wasn't a tweak event then + * ignore USER_RELEASECONFIRM setting: see [#26756] */ + if (ELEM(tweak_event, EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R) == 0) { + return 1; + } + } + } + else { + /* this is fine as long as not doing km-release, otherwise + * some items (i.e. markers) being tweaked may end up getting + * dropped all over + */ + if (event->val != KM_RELEASE) { + return 1; + } + } + + return 0; } bool WM_event_type_mask_test(const int event_type, const enum eEventType_Mask mask) { - /* Keyboard. */ - if (mask & EVT_TYPE_MASK_KEYBOARD) { - if (ISKEYBOARD(event_type)) { - return true; - } - } - else if (mask & EVT_TYPE_MASK_KEYBOARD_MODIFIER) { - if (ISKEYMODIFIER(event_type)) { - return true; - } - } - - /* Mouse. */ - if (mask & EVT_TYPE_MASK_MOUSE) { - if (ISMOUSE(event_type)) { - return true; - } - } - else if (mask & EVT_TYPE_MASK_MOUSE_WHEEL) { - if (ISMOUSE_WHEEL(event_type)) { - return true; - } - } - else if (mask & EVT_TYPE_MASK_MOUSE_GESTURE) { - if (ISMOUSE_GESTURE(event_type)) { - return true; - } - } - - /* Tweak. */ - if (mask & EVT_TYPE_MASK_TWEAK) { - if (ISTWEAK(event_type)) { - return true; - } - } - - /* Action Zone. */ - if (mask & EVT_TYPE_MASK_ACTIONZONE) { - if (IS_EVENT_ACTIONZONE(event_type)) { - return true; - } - } - - return false; + /* Keyboard. */ + if (mask & EVT_TYPE_MASK_KEYBOARD) { + if (ISKEYBOARD(event_type)) { + return true; + } + } + else if (mask & EVT_TYPE_MASK_KEYBOARD_MODIFIER) { + if (ISKEYMODIFIER(event_type)) { + return true; + } + } + + /* Mouse. */ + if (mask & EVT_TYPE_MASK_MOUSE) { + if (ISMOUSE(event_type)) { + return true; + } + } + else if (mask & EVT_TYPE_MASK_MOUSE_WHEEL) { + if (ISMOUSE_WHEEL(event_type)) { + return true; + } + } + else if (mask & EVT_TYPE_MASK_MOUSE_GESTURE) { + if (ISMOUSE_GESTURE(event_type)) { + return true; + } + } + + /* Tweak. */ + if (mask & EVT_TYPE_MASK_TWEAK) { + if (ISTWEAK(event_type)) { + return true; + } + } + + /* Action Zone. */ + if (mask & EVT_TYPE_MASK_ACTIONZONE) { + if (IS_EVENT_ACTIONZONE(event_type)) { + return true; + } + } + + return false; } /* ********************* ghost stuff *************** */ static int convert_key(GHOST_TKey key) { - if (key >= GHOST_kKeyA && key <= GHOST_kKeyZ) { - return (AKEY + ((int) key - GHOST_kKeyA)); - } - else if (key >= GHOST_kKey0 && key <= GHOST_kKey9) { - return (ZEROKEY + ((int) key - GHOST_kKey0)); - } - else if (key >= GHOST_kKeyNumpad0 && key <= GHOST_kKeyNumpad9) { - return (PAD0 + ((int) key - GHOST_kKeyNumpad0)); - } - else if (key >= GHOST_kKeyF1 && key <= GHOST_kKeyF19) { - return (F1KEY + ((int) key - GHOST_kKeyF1)); - } - else { - switch (key) { - case GHOST_kKeyBackSpace: return BACKSPACEKEY; - case GHOST_kKeyTab: return TABKEY; - case GHOST_kKeyLinefeed: return LINEFEEDKEY; - case GHOST_kKeyClear: return 0; - case GHOST_kKeyEnter: return RETKEY; - - case GHOST_kKeyEsc: return ESCKEY; - case GHOST_kKeySpace: return SPACEKEY; - case GHOST_kKeyQuote: return QUOTEKEY; - case GHOST_kKeyComma: return COMMAKEY; - case GHOST_kKeyMinus: return MINUSKEY; - case GHOST_kKeyPlus: return PLUSKEY; - case GHOST_kKeyPeriod: return PERIODKEY; - case GHOST_kKeySlash: return SLASHKEY; - - case GHOST_kKeySemicolon: return SEMICOLONKEY; - case GHOST_kKeyEqual: return EQUALKEY; - - case GHOST_kKeyLeftBracket: return LEFTBRACKETKEY; - case GHOST_kKeyRightBracket: return RIGHTBRACKETKEY; - case GHOST_kKeyBackslash: return BACKSLASHKEY; - case GHOST_kKeyAccentGrave: return ACCENTGRAVEKEY; - - case GHOST_kKeyLeftShift: return LEFTSHIFTKEY; - case GHOST_kKeyRightShift: return RIGHTSHIFTKEY; - case GHOST_kKeyLeftControl: return LEFTCTRLKEY; - case GHOST_kKeyRightControl: return RIGHTCTRLKEY; - case GHOST_kKeyOS: return OSKEY; - case GHOST_kKeyLeftAlt: return LEFTALTKEY; - case GHOST_kKeyRightAlt: return RIGHTALTKEY; - - case GHOST_kKeyCapsLock: return CAPSLOCKKEY; - case GHOST_kKeyNumLock: return 0; - case GHOST_kKeyScrollLock: return 0; - - case GHOST_kKeyLeftArrow: return LEFTARROWKEY; - case GHOST_kKeyRightArrow: return RIGHTARROWKEY; - case GHOST_kKeyUpArrow: return UPARROWKEY; - case GHOST_kKeyDownArrow: return DOWNARROWKEY; - - case GHOST_kKeyPrintScreen: return 0; - case GHOST_kKeyPause: return PAUSEKEY; - - case GHOST_kKeyInsert: return INSERTKEY; - case GHOST_kKeyDelete: return DELKEY; - case GHOST_kKeyHome: return HOMEKEY; - case GHOST_kKeyEnd: return ENDKEY; - case GHOST_kKeyUpPage: return PAGEUPKEY; - case GHOST_kKeyDownPage: return PAGEDOWNKEY; - - case GHOST_kKeyNumpadPeriod: return PADPERIOD; - case GHOST_kKeyNumpadEnter: return PADENTER; - case GHOST_kKeyNumpadPlus: return PADPLUSKEY; - case GHOST_kKeyNumpadMinus: return PADMINUS; - case GHOST_kKeyNumpadAsterisk: return PADASTERKEY; - case GHOST_kKeyNumpadSlash: return PADSLASHKEY; - - case GHOST_kKeyGrLess: return GRLESSKEY; - - case GHOST_kKeyMediaPlay: return MEDIAPLAY; - case GHOST_kKeyMediaStop: return MEDIASTOP; - case GHOST_kKeyMediaFirst: return MEDIAFIRST; - case GHOST_kKeyMediaLast: return MEDIALAST; - - default: - return UNKNOWNKEY; /* GHOST_kKeyUnknown */ - } - } + if (key >= GHOST_kKeyA && key <= GHOST_kKeyZ) { + return (AKEY + ((int)key - GHOST_kKeyA)); + } + else if (key >= GHOST_kKey0 && key <= GHOST_kKey9) { + return (ZEROKEY + ((int)key - GHOST_kKey0)); + } + else if (key >= GHOST_kKeyNumpad0 && key <= GHOST_kKeyNumpad9) { + return (PAD0 + ((int)key - GHOST_kKeyNumpad0)); + } + else if (key >= GHOST_kKeyF1 && key <= GHOST_kKeyF19) { + return (F1KEY + ((int)key - GHOST_kKeyF1)); + } + else { + switch (key) { + case GHOST_kKeyBackSpace: + return BACKSPACEKEY; + case GHOST_kKeyTab: + return TABKEY; + case GHOST_kKeyLinefeed: + return LINEFEEDKEY; + case GHOST_kKeyClear: + return 0; + case GHOST_kKeyEnter: + return RETKEY; + + case GHOST_kKeyEsc: + return ESCKEY; + case GHOST_kKeySpace: + return SPACEKEY; + case GHOST_kKeyQuote: + return QUOTEKEY; + case GHOST_kKeyComma: + return COMMAKEY; + case GHOST_kKeyMinus: + return MINUSKEY; + case GHOST_kKeyPlus: + return PLUSKEY; + case GHOST_kKeyPeriod: + return PERIODKEY; + case GHOST_kKeySlash: + return SLASHKEY; + + case GHOST_kKeySemicolon: + return SEMICOLONKEY; + case GHOST_kKeyEqual: + return EQUALKEY; + + case GHOST_kKeyLeftBracket: + return LEFTBRACKETKEY; + case GHOST_kKeyRightBracket: + return RIGHTBRACKETKEY; + case GHOST_kKeyBackslash: + return BACKSLASHKEY; + case GHOST_kKeyAccentGrave: + return ACCENTGRAVEKEY; + + case GHOST_kKeyLeftShift: + return LEFTSHIFTKEY; + case GHOST_kKeyRightShift: + return RIGHTSHIFTKEY; + case GHOST_kKeyLeftControl: + return LEFTCTRLKEY; + case GHOST_kKeyRightControl: + return RIGHTCTRLKEY; + case GHOST_kKeyOS: + return OSKEY; + case GHOST_kKeyLeftAlt: + return LEFTALTKEY; + case GHOST_kKeyRightAlt: + return RIGHTALTKEY; + + case GHOST_kKeyCapsLock: + return CAPSLOCKKEY; + case GHOST_kKeyNumLock: + return 0; + case GHOST_kKeyScrollLock: + return 0; + + case GHOST_kKeyLeftArrow: + return LEFTARROWKEY; + case GHOST_kKeyRightArrow: + return RIGHTARROWKEY; + case GHOST_kKeyUpArrow: + return UPARROWKEY; + case GHOST_kKeyDownArrow: + return DOWNARROWKEY; + + case GHOST_kKeyPrintScreen: + return 0; + case GHOST_kKeyPause: + return PAUSEKEY; + + case GHOST_kKeyInsert: + return INSERTKEY; + case GHOST_kKeyDelete: + return DELKEY; + case GHOST_kKeyHome: + return HOMEKEY; + case GHOST_kKeyEnd: + return ENDKEY; + case GHOST_kKeyUpPage: + return PAGEUPKEY; + case GHOST_kKeyDownPage: + return PAGEDOWNKEY; + + case GHOST_kKeyNumpadPeriod: + return PADPERIOD; + case GHOST_kKeyNumpadEnter: + return PADENTER; + case GHOST_kKeyNumpadPlus: + return PADPLUSKEY; + case GHOST_kKeyNumpadMinus: + return PADMINUS; + case GHOST_kKeyNumpadAsterisk: + return PADASTERKEY; + case GHOST_kKeyNumpadSlash: + return PADSLASHKEY; + + case GHOST_kKeyGrLess: + return GRLESSKEY; + + case GHOST_kKeyMediaPlay: + return MEDIAPLAY; + case GHOST_kKeyMediaStop: + return MEDIASTOP; + case GHOST_kKeyMediaFirst: + return MEDIAFIRST; + case GHOST_kKeyMediaLast: + return MEDIALAST; + + default: + return UNKNOWNKEY; /* GHOST_kKeyUnknown */ + } + } } static void wm_eventemulation(wmEvent *event, bool test_only) { - /* Store last mmb/rmb event value to make emulation work when modifier keys - * are released first. This really should be in a data structure somewhere. */ - static int emulating_event = EVENT_NONE; - - /* middlemouse and rightmouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->alt) { - event->type = MIDDLEMOUSE; - event->alt = 0; - - if (!test_only) { - emulating_event = MIDDLEMOUSE; - } - } + /* Store last mmb/rmb event value to make emulation work when modifier keys + * are released first. This really should be in a data structure somewhere. */ + static int emulating_event = EVENT_NONE; + + /* middlemouse and rightmouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->alt) { + event->type = MIDDLEMOUSE; + event->alt = 0; + + if (!test_only) { + emulating_event = MIDDLEMOUSE; + } + } #ifdef __APPLE__ - else if (event->val == KM_PRESS && event->oskey) { - event->type = RIGHTMOUSE; - event->oskey = 0; - - if (!test_only) { - emulating_event = RIGHTMOUSE; - } - } + else if (event->val == KM_PRESS && event->oskey) { + event->type = RIGHTMOUSE; + event->oskey = 0; + + if (!test_only) { + emulating_event = RIGHTMOUSE; + } + } #endif - else if (event->val == KM_RELEASE) { - /* only send middle-mouse release if emulated */ - if (emulating_event == MIDDLEMOUSE) { - event->type = MIDDLEMOUSE; - event->alt = 0; - } - else if (emulating_event == RIGHTMOUSE) { - event->type = RIGHTMOUSE; - event->oskey = 0; - } - - if (!test_only) { - emulating_event = EVENT_NONE; - } - } - } - - } - - /* numpad emulation */ - if (U.flag & USER_NONUMPAD) { - switch (event->type) { - case ZEROKEY: event->type = PAD0; break; - case ONEKEY: event->type = PAD1; break; - case TWOKEY: event->type = PAD2; break; - case THREEKEY: event->type = PAD3; break; - case FOURKEY: event->type = PAD4; break; - case FIVEKEY: event->type = PAD5; break; - case SIXKEY: event->type = PAD6; break; - case SEVENKEY: event->type = PAD7; break; - case EIGHTKEY: event->type = PAD8; break; - case NINEKEY: event->type = PAD9; break; - case MINUSKEY: event->type = PADMINUS; break; - case EQUALKEY: event->type = PADPLUSKEY; break; - case BACKSLASHKEY: event->type = PADSLASHKEY; break; - } - } + else if (event->val == KM_RELEASE) { + /* only send middle-mouse release if emulated */ + if (emulating_event == MIDDLEMOUSE) { + event->type = MIDDLEMOUSE; + event->alt = 0; + } + else if (emulating_event == RIGHTMOUSE) { + event->type = RIGHTMOUSE; + event->oskey = 0; + } + + if (!test_only) { + emulating_event = EVENT_NONE; + } + } + } + } + + /* numpad emulation */ + if (U.flag & USER_NONUMPAD) { + switch (event->type) { + case ZEROKEY: + event->type = PAD0; + break; + case ONEKEY: + event->type = PAD1; + break; + case TWOKEY: + event->type = PAD2; + break; + case THREEKEY: + event->type = PAD3; + break; + case FOURKEY: + event->type = PAD4; + break; + case FIVEKEY: + event->type = PAD5; + break; + case SIXKEY: + event->type = PAD6; + break; + case SEVENKEY: + event->type = PAD7; + break; + case EIGHTKEY: + event->type = PAD8; + break; + case NINEKEY: + event->type = PAD9; + break; + case MINUSKEY: + event->type = PADMINUS; + break; + case EQUALKEY: + event->type = PADPLUSKEY; + break; + case BACKSLASHKEY: + event->type = PADSLASHKEY; + break; + } + } } /* applies the global tablet pressure correction curve */ float wm_pressure_curve(float pressure) { - if (U.pressure_threshold_max != 0.0f) { - pressure /= U.pressure_threshold_max; - } + if (U.pressure_threshold_max != 0.0f) { + pressure /= U.pressure_threshold_max; + } - CLAMP(pressure, 0.0f, 1.0f); + CLAMP(pressure, 0.0f, 1.0f); - if (U.pressure_softness != 0.0f) { - pressure = powf(pressure, powf(4.0f, -U.pressure_softness)); - } + if (U.pressure_softness != 0.0f) { + pressure = powf(pressure, powf(4.0f, -U.pressure_softness)); + } - return pressure; + return pressure; } /* adds customdata to event */ static void update_tablet_data(wmWindow *win, wmEvent *event) { - const GHOST_TabletData *td = GHOST_GetTabletData(win->ghostwin); - - /* if there's tablet data from an active tablet device then add it */ - if ((td != NULL) && td->Active != GHOST_kTabletModeNone) { - struct wmTabletData *wmtab = MEM_mallocN(sizeof(wmTabletData), "customdata tablet"); - - wmtab->Active = (int)td->Active; - wmtab->Pressure = wm_pressure_curve(td->Pressure); - wmtab->Xtilt = td->Xtilt; - wmtab->Ytilt = td->Ytilt; - - event->tablet_data = wmtab; - // printf("%s: using tablet %.5f\n", __func__, wmtab->Pressure); - } - else { - event->tablet_data = NULL; - // printf("%s: not using tablet\n", __func__); - } + const GHOST_TabletData *td = GHOST_GetTabletData(win->ghostwin); + + /* if there's tablet data from an active tablet device then add it */ + if ((td != NULL) && td->Active != GHOST_kTabletModeNone) { + struct wmTabletData *wmtab = MEM_mallocN(sizeof(wmTabletData), "customdata tablet"); + + wmtab->Active = (int)td->Active; + wmtab->Pressure = wm_pressure_curve(td->Pressure); + wmtab->Xtilt = td->Xtilt; + wmtab->Ytilt = td->Ytilt; + + event->tablet_data = wmtab; + // printf("%s: using tablet %.5f\n", __func__, wmtab->Pressure); + } + else { + event->tablet_data = NULL; + // printf("%s: not using tablet\n", __func__); + } } #ifdef WITH_INPUT_NDOF /* adds customdata to event */ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *ghost) { - wmNDOFMotionData *data = MEM_mallocN(sizeof(wmNDOFMotionData), "customdata NDOF"); + wmNDOFMotionData *data = MEM_mallocN(sizeof(wmNDOFMotionData), "customdata NDOF"); - const float ts = U.ndof_sensitivity; - const float rs = U.ndof_orbit_sensitivity; + const float ts = U.ndof_sensitivity; + const float rs = U.ndof_orbit_sensitivity; - mul_v3_v3fl(data->tvec, &ghost->tx, ts); - mul_v3_v3fl(data->rvec, &ghost->rx, rs); + mul_v3_v3fl(data->tvec, &ghost->tx, ts); + mul_v3_v3fl(data->rvec, &ghost->rx, rs); - if (U.ndof_flag & NDOF_PAN_YZ_SWAP_AXIS) { - float t; - t = data->tvec[1]; - data->tvec[1] = -data->tvec[2]; - data->tvec[2] = t; - } + if (U.ndof_flag & NDOF_PAN_YZ_SWAP_AXIS) { + float t; + t = data->tvec[1]; + data->tvec[1] = -data->tvec[2]; + data->tvec[2] = t; + } - data->dt = ghost->dt; + data->dt = ghost->dt; - data->progress = (wmProgress) ghost->progress; + data->progress = (wmProgress)ghost->progress; - event->custom = EVT_DATA_NDOF_MOTION; - event->customdata = data; - event->customdatafree = 1; + event->custom = EVT_DATA_NDOF_MOTION; + event->customdata = data; + event->customdatafree = 1; } #endif /* WITH_INPUT_NDOF */ /* imperfect but probably usable... draw/enable drags to other windows */ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event) { - int mx = event->x, my = event->y; - - if (wm->windows.first == wm->windows.last) { - return NULL; - } - - /* in order to use window size and mouse position (pixels), we have to use a WM function */ - - /* check if outside, include top window bar... */ - if (mx < 0 || my < 0 || mx > WM_window_pixels_x(win) || my > WM_window_pixels_y(win) + 30) { - wmWindow *owin; - wmEventHandler *handler; - - /* let's skip windows having modal handlers now */ - /* potential XXX ugly... I wouldn't have added a modalhandlers list (introduced in rev 23331, ton) */ - for (handler = win->modalhandlers.first; handler; handler = handler->next) { - if (ELEM(handler->type, WM_HANDLER_TYPE_UI, WM_HANDLER_TYPE_OP)) { - return NULL; - } - } - - /* to desktop space */ - mx += (int) (U.pixelsize * win->posx); - my += (int) (U.pixelsize * win->posy); - - /* check other windows to see if it has mouse inside */ - for (owin = wm->windows.first; owin; owin = owin->next) { - - if (owin != win) { - int posx = (int) (U.pixelsize * owin->posx); - int posy = (int) (U.pixelsize * owin->posy); - - if (mx - posx >= 0 && owin->posy >= 0 && - mx - posx <= WM_window_pixels_x(owin) && my - posy <= WM_window_pixels_y(owin)) - { - event->x = mx - (int)(U.pixelsize * owin->posx); - event->y = my - (int)(U.pixelsize * owin->posy); - - return owin; - } - } - } - } - return NULL; + int mx = event->x, my = event->y; + + if (wm->windows.first == wm->windows.last) { + return NULL; + } + + /* in order to use window size and mouse position (pixels), we have to use a WM function */ + + /* check if outside, include top window bar... */ + if (mx < 0 || my < 0 || mx > WM_window_pixels_x(win) || my > WM_window_pixels_y(win) + 30) { + wmWindow *owin; + wmEventHandler *handler; + + /* let's skip windows having modal handlers now */ + /* potential XXX ugly... I wouldn't have added a modalhandlers list (introduced in rev 23331, ton) */ + for (handler = win->modalhandlers.first; handler; handler = handler->next) { + if (ELEM(handler->type, WM_HANDLER_TYPE_UI, WM_HANDLER_TYPE_OP)) { + return NULL; + } + } + + /* to desktop space */ + mx += (int)(U.pixelsize * win->posx); + my += (int)(U.pixelsize * win->posy); + + /* check other windows to see if it has mouse inside */ + for (owin = wm->windows.first; owin; owin = owin->next) { + + if (owin != win) { + int posx = (int)(U.pixelsize * owin->posx); + int posy = (int)(U.pixelsize * owin->posy); + + if (mx - posx >= 0 && owin->posy >= 0 && mx - posx <= WM_window_pixels_x(owin) && + my - posy <= WM_window_pixels_y(owin)) { + event->x = mx - (int)(U.pixelsize * owin->posx); + event->y = my - (int)(U.pixelsize * owin->posy); + + return owin; + } + } + } + } + return NULL; } static bool wm_event_is_double_click(wmEvent *event, const wmEvent *event_state) { - if ((event->type == event_state->prevtype) && - (event_state->prevval == KM_RELEASE) && - (event->val == KM_PRESS)) - { - if ((ISMOUSE(event->type) == false) || - ((abs(event->x - event_state->prevclickx)) < WM_EVENT_CLICK_TWEAK_THRESHOLD && - (abs(event->y - event_state->prevclicky)) < WM_EVENT_CLICK_TWEAK_THRESHOLD)) - { - if ((PIL_check_seconds_timer() - event_state->prevclicktime) * 1000 < U.dbl_click_time) { - return true; - } - } - } - - return false; + if ((event->type == event_state->prevtype) && (event_state->prevval == KM_RELEASE) && + (event->val == KM_PRESS)) { + if ((ISMOUSE(event->type) == false) || + ((abs(event->x - event_state->prevclickx)) < WM_EVENT_CLICK_TWEAK_THRESHOLD && + (abs(event->y - event_state->prevclicky)) < WM_EVENT_CLICK_TWEAK_THRESHOLD)) { + if ((PIL_check_seconds_timer() - event_state->prevclicktime) * 1000 < U.dbl_click_time) { + return true; + } + } + } + + return false; } static wmEvent *wm_event_add_mousemove(wmWindow *win, const wmEvent *event) { - wmEvent *event_last = win->queue.last; - - /* some painting operators want accurate mouse events, they can - * handle in between mouse move moves, others can happily ignore - * them for better performance */ - if (event_last && event_last->type == MOUSEMOVE) { - event_last->type = INBETWEEN_MOUSEMOVE; - } - - wmEvent *event_new = wm_event_add(win, event); - if (event_last == NULL) { - event_last = win->eventstate; - } - - copy_v2_v2_int(&event_new->prevx, &event_last->x); - return event_new; + wmEvent *event_last = win->queue.last; + + /* some painting operators want accurate mouse events, they can + * handle in between mouse move moves, others can happily ignore + * them for better performance */ + if (event_last && event_last->type == MOUSEMOVE) { + event_last->type = INBETWEEN_MOUSEMOVE; + } + + wmEvent *event_new = wm_event_add(win, event); + if (event_last == NULL) { + event_last = win->eventstate; + } + + copy_v2_v2_int(&event_new->prevx, &event_last->x); + return event_new; } /* windows store own event queues, no bContext here */ /* time is in 1000s of seconds, from ghost */ -void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int UNUSED(time), void *customdata) +void wm_event_add_ghostevent( + wmWindowManager *wm, wmWindow *win, int type, int UNUSED(time), void *customdata) { - wmWindow *owin; - - if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) { - return; - } - - /* Having both, event and evt, can be highly confusing to work with, but is necessary for - * our current event system, so let's clear things up a bit: - * - data added to event only will be handled immediately, but will not be copied to the next event - * - data added to evt only stays, but is handled with the next event -> execution delay - * - data added to event and evt stays and is handled immediately - */ - wmEvent event, *evt = win->eventstate; - - /* initialize and copy state (only mouse x y and modifiers) */ - event = *evt; - - switch (type) { - /* mouse move, also to inactive window (X11 does this) */ - case GHOST_kEventCursorMove: - { - GHOST_TEventCursorData *cd = customdata; - - copy_v2_v2_int(&event.x, &cd->x); - wm_stereo3d_mouse_offset_apply(win, &event.x); - - event.type = MOUSEMOVE; - { - wmEvent *event_new = wm_event_add_mousemove(win, &event); - copy_v2_v2_int(&evt->x, &event_new->x); - evt->is_motion_absolute = event_new->is_motion_absolute; - } - - /* also add to other window if event is there, this makes overdraws disappear nicely */ - /* it remaps mousecoord to other window in event */ - owin = wm_event_cursor_other_windows(wm, win, &event); - if (owin) { - wmEvent oevent, *oevt = owin->eventstate; - - oevent = *oevt; - - copy_v2_v2_int(&oevent.x, &event.x); - oevent.type = MOUSEMOVE; - { - wmEvent *event_new = wm_event_add_mousemove(owin, &oevent); - copy_v2_v2_int(&oevt->x, &event_new->x); - oevt->is_motion_absolute = event_new->is_motion_absolute; - } - } - - break; - } - case GHOST_kEventTrackpad: - { - GHOST_TEventTrackpadData *pd = customdata; - switch (pd->subtype) { - case GHOST_kTrackpadEventMagnify: - event.type = MOUSEZOOM; - pd->deltaX = -pd->deltaX; - pd->deltaY = -pd->deltaY; - break; - case GHOST_kTrackpadEventRotate: - event.type = MOUSEROTATE; - break; - case GHOST_kTrackpadEventScroll: - default: - event.type = MOUSEPAN; - break; - } - - event.x = evt->x = pd->x; - event.y = evt->y = pd->y; - event.val = KM_NOTHING; - - /* Use prevx/prevy so we can calculate the delta later */ - event.prevx = event.x - pd->deltaX; - event.prevy = event.y - (-pd->deltaY); - - wm_event_add(win, &event); - break; - } - /* mouse button */ - case GHOST_kEventButtonDown: - case GHOST_kEventButtonUp: - { - GHOST_TEventButtonData *bd = customdata; - - /* get value and type from ghost */ - event.val = (type == GHOST_kEventButtonDown) ? KM_PRESS : KM_RELEASE; - - if (bd->button == GHOST_kButtonMaskLeft) { - event.type = LEFTMOUSE; - } - else if (bd->button == GHOST_kButtonMaskRight) { - event.type = RIGHTMOUSE; - } - else if (bd->button == GHOST_kButtonMaskButton4) { - event.type = BUTTON4MOUSE; - } - else if (bd->button == GHOST_kButtonMaskButton5) { - event.type = BUTTON5MOUSE; - } - else if (bd->button == GHOST_kButtonMaskButton6) { - event.type = BUTTON6MOUSE; - } - else if (bd->button == GHOST_kButtonMaskButton7) { - event.type = BUTTON7MOUSE; - } - else { - event.type = MIDDLEMOUSE; - } - - wm_eventemulation(&event, false); - - /* copy previous state to prev event state (two old!) */ - evt->prevval = evt->val; - evt->prevtype = evt->type; - - /* copy to event state */ - evt->val = event.val; - evt->type = event.type; - - 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; - } - - /* double click test */ - if (wm_event_is_double_click(&event, evt)) { - CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click"); - event.val = KM_DBL_CLICK; - } - if (event.val == KM_PRESS) { - evt->prevclicktime = PIL_check_seconds_timer(); - evt->prevclickx = event.x; - evt->prevclicky = event.y; - } - - /* add to other window if event is there (not to both!) */ - owin = wm_event_cursor_other_windows(wm, win, &event); - if (owin) { - wmEvent oevent = *(owin->eventstate); - - oevent.x = event.x; - oevent.y = event.y; - oevent.type = event.type; - oevent.val = event.val; - - wm_event_add(owin, &oevent); - } - else { - wm_event_add(win, &event); - } - - break; - } - /* keyboard */ - case GHOST_kEventKeyDown: - case GHOST_kEventKeyUp: - { - GHOST_TEventKeyData *kd = customdata; - short keymodifier = KM_NOTHING; - event.type = convert_key(kd->key); - event.ascii = kd->ascii; - memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/ - event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; - - wm_eventemulation(&event, false); - - /* copy previous state to prev event state (two old!) */ - evt->prevval = evt->val; - evt->prevtype = evt->type; - - /* copy to event state */ - evt->val = event.val; - evt->type = event.type; - - /* exclude arrow keys, esc, etc from text input */ - if (type == GHOST_kEventKeyUp) { - event.ascii = '\0'; - - /* ghost should do this already for key up */ - if (event.utf8_buf[0]) { - CLOG_ERROR(WM_LOG_EVENTS, "ghost on your platform is misbehaving, utf8 events on key up!"); - } - event.utf8_buf[0] = '\0'; - } - else { - if (event.ascii < 32 && event.ascii > 0) { - event.ascii = '\0'; - } - if (event.utf8_buf[0] < 32 && event.utf8_buf[0] > 0) { - event.utf8_buf[0] = '\0'; - } - } - - if (event.utf8_buf[0]) { - if (BLI_str_utf8_size(event.utf8_buf) == -1) { - CLOG_ERROR(WM_LOG_EVENTS, - "ghost detected an invalid unicode character '%d'", - (int)(unsigned char)event.utf8_buf[0]); - event.utf8_buf[0] = '\0'; - } - } - - /* assigning both first and second is strange - campbell */ - switch (event.type) { - case LEFTSHIFTKEY: - case RIGHTSHIFTKEY: - if (event.val == KM_PRESS) { - if (evt->ctrl || evt->alt || evt->oskey) { - keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); - } - else { - keymodifier = KM_MOD_FIRST; - } - } - event.shift = evt->shift = keymodifier; - break; - case LEFTCTRLKEY: - case RIGHTCTRLKEY: - if (event.val == KM_PRESS) { - if (evt->shift || evt->alt || evt->oskey) { - keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); - } - else { - keymodifier = KM_MOD_FIRST; - } - } - event.ctrl = evt->ctrl = keymodifier; - break; - case LEFTALTKEY: - case RIGHTALTKEY: - if (event.val == KM_PRESS) { - if (evt->ctrl || evt->shift || evt->oskey) { - keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); - } - else { - keymodifier = KM_MOD_FIRST; - } - } - event.alt = evt->alt = keymodifier; - break; - case OSKEY: - if (event.val == KM_PRESS) { - if (evt->ctrl || evt->alt || evt->shift) { - keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); - } - else { - keymodifier = KM_MOD_FIRST; - } - } - event.oskey = evt->oskey = keymodifier; - break; - default: - if (event.val == KM_PRESS && event.keymodifier == 0) { - /* Only set in eventstate, for next event. */ - evt->keymodifier = event.type; - } - else if (event.val == KM_RELEASE && event.keymodifier == event.type) { - event.keymodifier = evt->keymodifier = 0; - } - break; - } - - /* double click test */ - /* if previous event was same type, and previous was release, and now it presses... */ - if (wm_event_is_double_click(&event, evt)) { - CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click"); - event.val = KM_DBL_CLICK; - } - - /* this case happens on holding a key pressed, it should not generate - * press events events with the same key as modifier */ - if (event.keymodifier == event.type) { - event.keymodifier = 0; - } - - /* this case happens with an external numpad, and also when using 'dead keys' (to compose complex latin - * characters e.g.), it's not really clear why. - * Since it's impossible to map a key modifier to an unknown key, it shouldn't harm to clear it. */ - if (event.keymodifier == UNKNOWNKEY) { - evt->keymodifier = event.keymodifier = 0; - } - - /* if test_break set, it catches this. Do not set with modifier presses. XXX Keep global for now? */ - if ((event.type == ESCKEY && event.val == KM_PRESS) && - /* check other modifiers because ms-windows uses these to bring up the task manager */ - (event.shift == 0 && event.ctrl == 0 && event.alt == 0)) - { - G.is_break = true; - } - - /* double click test - only for press */ - if (event.val == KM_PRESS) { - /* Don't reset timer & location when holding the key generates repeat events. */ - if ((evt->prevtype != event.type) || (evt->prevval != KM_PRESS)) { - evt->prevclicktime = PIL_check_seconds_timer(); - evt->prevclickx = event.x; - evt->prevclicky = event.y; - } - } - - wm_event_add(win, &event); - - break; - } - - case GHOST_kEventWheel: - { - GHOST_TEventWheelData *wheelData = customdata; - - if (wheelData->z > 0) { - event.type = WHEELUPMOUSE; - } - else { - event.type = WHEELDOWNMOUSE; - } - - event.val = KM_PRESS; - wm_event_add(win, &event); - - break; - } - case GHOST_kEventTimer: - { - event.type = TIMER; - event.custom = EVT_DATA_TIMER; - event.customdata = customdata; - event.val = KM_NOTHING; - event.keymodifier = 0; - wm_event_add(win, &event); - - break; - } + wmWindow *owin; + + if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) { + return; + } + + /* Having both, event and evt, can be highly confusing to work with, but is necessary for + * our current event system, so let's clear things up a bit: + * - data added to event only will be handled immediately, but will not be copied to the next event + * - data added to evt only stays, but is handled with the next event -> execution delay + * - data added to event and evt stays and is handled immediately + */ + wmEvent event, *evt = win->eventstate; + + /* initialize and copy state (only mouse x y and modifiers) */ + event = *evt; + + switch (type) { + /* mouse move, also to inactive window (X11 does this) */ + case GHOST_kEventCursorMove: { + GHOST_TEventCursorData *cd = customdata; + + copy_v2_v2_int(&event.x, &cd->x); + wm_stereo3d_mouse_offset_apply(win, &event.x); + + event.type = MOUSEMOVE; + { + wmEvent *event_new = wm_event_add_mousemove(win, &event); + copy_v2_v2_int(&evt->x, &event_new->x); + evt->is_motion_absolute = event_new->is_motion_absolute; + } + + /* also add to other window if event is there, this makes overdraws disappear nicely */ + /* it remaps mousecoord to other window in event */ + owin = wm_event_cursor_other_windows(wm, win, &event); + if (owin) { + wmEvent oevent, *oevt = owin->eventstate; + + oevent = *oevt; + + copy_v2_v2_int(&oevent.x, &event.x); + oevent.type = MOUSEMOVE; + { + wmEvent *event_new = wm_event_add_mousemove(owin, &oevent); + copy_v2_v2_int(&oevt->x, &event_new->x); + oevt->is_motion_absolute = event_new->is_motion_absolute; + } + } + + break; + } + case GHOST_kEventTrackpad: { + GHOST_TEventTrackpadData *pd = customdata; + switch (pd->subtype) { + case GHOST_kTrackpadEventMagnify: + event.type = MOUSEZOOM; + pd->deltaX = -pd->deltaX; + pd->deltaY = -pd->deltaY; + break; + case GHOST_kTrackpadEventRotate: + event.type = MOUSEROTATE; + break; + case GHOST_kTrackpadEventScroll: + default: + event.type = MOUSEPAN; + break; + } + + event.x = evt->x = pd->x; + event.y = evt->y = pd->y; + event.val = KM_NOTHING; + + /* Use prevx/prevy so we can calculate the delta later */ + event.prevx = event.x - pd->deltaX; + event.prevy = event.y - (-pd->deltaY); + + wm_event_add(win, &event); + break; + } + /* mouse button */ + case GHOST_kEventButtonDown: + case GHOST_kEventButtonUp: { + GHOST_TEventButtonData *bd = customdata; + + /* get value and type from ghost */ + event.val = (type == GHOST_kEventButtonDown) ? KM_PRESS : KM_RELEASE; + + if (bd->button == GHOST_kButtonMaskLeft) { + event.type = LEFTMOUSE; + } + else if (bd->button == GHOST_kButtonMaskRight) { + event.type = RIGHTMOUSE; + } + else if (bd->button == GHOST_kButtonMaskButton4) { + event.type = BUTTON4MOUSE; + } + else if (bd->button == GHOST_kButtonMaskButton5) { + event.type = BUTTON5MOUSE; + } + else if (bd->button == GHOST_kButtonMaskButton6) { + event.type = BUTTON6MOUSE; + } + else if (bd->button == GHOST_kButtonMaskButton7) { + event.type = BUTTON7MOUSE; + } + else { + event.type = MIDDLEMOUSE; + } + + wm_eventemulation(&event, false); + + /* copy previous state to prev event state (two old!) */ + evt->prevval = evt->val; + evt->prevtype = evt->type; + + /* copy to event state */ + evt->val = event.val; + evt->type = event.type; + + 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; + } + + /* double click test */ + if (wm_event_is_double_click(&event, evt)) { + CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click"); + event.val = KM_DBL_CLICK; + } + if (event.val == KM_PRESS) { + evt->prevclicktime = PIL_check_seconds_timer(); + evt->prevclickx = event.x; + evt->prevclicky = event.y; + } + + /* add to other window if event is there (not to both!) */ + owin = wm_event_cursor_other_windows(wm, win, &event); + if (owin) { + wmEvent oevent = *(owin->eventstate); + + oevent.x = event.x; + oevent.y = event.y; + oevent.type = event.type; + oevent.val = event.val; + + wm_event_add(owin, &oevent); + } + else { + wm_event_add(win, &event); + } + + break; + } + /* keyboard */ + case GHOST_kEventKeyDown: + case GHOST_kEventKeyUp: { + GHOST_TEventKeyData *kd = customdata; + short keymodifier = KM_NOTHING; + event.type = convert_key(kd->key); + event.ascii = kd->ascii; + memcpy( + event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/ + event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; + + wm_eventemulation(&event, false); + + /* copy previous state to prev event state (two old!) */ + evt->prevval = evt->val; + evt->prevtype = evt->type; + + /* copy to event state */ + evt->val = event.val; + evt->type = event.type; + + /* exclude arrow keys, esc, etc from text input */ + if (type == GHOST_kEventKeyUp) { + event.ascii = '\0'; + + /* ghost should do this already for key up */ + if (event.utf8_buf[0]) { + CLOG_ERROR(WM_LOG_EVENTS, + "ghost on your platform is misbehaving, utf8 events on key up!"); + } + event.utf8_buf[0] = '\0'; + } + else { + if (event.ascii < 32 && event.ascii > 0) { + event.ascii = '\0'; + } + if (event.utf8_buf[0] < 32 && event.utf8_buf[0] > 0) { + event.utf8_buf[0] = '\0'; + } + } + + if (event.utf8_buf[0]) { + if (BLI_str_utf8_size(event.utf8_buf) == -1) { + CLOG_ERROR(WM_LOG_EVENTS, + "ghost detected an invalid unicode character '%d'", + (int)(unsigned char)event.utf8_buf[0]); + event.utf8_buf[0] = '\0'; + } + } + + /* assigning both first and second is strange - campbell */ + switch (event.type) { + case LEFTSHIFTKEY: + case RIGHTSHIFTKEY: + if (event.val == KM_PRESS) { + if (evt->ctrl || evt->alt || evt->oskey) { + keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); + } + else { + keymodifier = KM_MOD_FIRST; + } + } + event.shift = evt->shift = keymodifier; + break; + case LEFTCTRLKEY: + case RIGHTCTRLKEY: + if (event.val == KM_PRESS) { + if (evt->shift || evt->alt || evt->oskey) { + keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); + } + else { + keymodifier = KM_MOD_FIRST; + } + } + event.ctrl = evt->ctrl = keymodifier; + break; + case LEFTALTKEY: + case RIGHTALTKEY: + if (event.val == KM_PRESS) { + if (evt->ctrl || evt->shift || evt->oskey) { + keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); + } + else { + keymodifier = KM_MOD_FIRST; + } + } + event.alt = evt->alt = keymodifier; + break; + case OSKEY: + if (event.val == KM_PRESS) { + if (evt->ctrl || evt->alt || evt->shift) { + keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); + } + else { + keymodifier = KM_MOD_FIRST; + } + } + event.oskey = evt->oskey = keymodifier; + break; + default: + if (event.val == KM_PRESS && event.keymodifier == 0) { + /* Only set in eventstate, for next event. */ + evt->keymodifier = event.type; + } + else if (event.val == KM_RELEASE && event.keymodifier == event.type) { + event.keymodifier = evt->keymodifier = 0; + } + break; + } + + /* double click test */ + /* if previous event was same type, and previous was release, and now it presses... */ + if (wm_event_is_double_click(&event, evt)) { + CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click"); + event.val = KM_DBL_CLICK; + } + + /* this case happens on holding a key pressed, it should not generate + * press events events with the same key as modifier */ + if (event.keymodifier == event.type) { + event.keymodifier = 0; + } + + /* this case happens with an external numpad, and also when using 'dead keys' (to compose complex latin + * characters e.g.), it's not really clear why. + * Since it's impossible to map a key modifier to an unknown key, it shouldn't harm to clear it. */ + if (event.keymodifier == UNKNOWNKEY) { + evt->keymodifier = event.keymodifier = 0; + } + + /* if test_break set, it catches this. Do not set with modifier presses. XXX Keep global for now? */ + if ((event.type == ESCKEY && event.val == KM_PRESS) && + /* check other modifiers because ms-windows uses these to bring up the task manager */ + (event.shift == 0 && event.ctrl == 0 && event.alt == 0)) { + G.is_break = true; + } + + /* double click test - only for press */ + if (event.val == KM_PRESS) { + /* Don't reset timer & location when holding the key generates repeat events. */ + if ((evt->prevtype != event.type) || (evt->prevval != KM_PRESS)) { + evt->prevclicktime = PIL_check_seconds_timer(); + evt->prevclickx = event.x; + evt->prevclicky = event.y; + } + } + + wm_event_add(win, &event); + + break; + } + + case GHOST_kEventWheel: { + GHOST_TEventWheelData *wheelData = customdata; + + if (wheelData->z > 0) { + event.type = WHEELUPMOUSE; + } + else { + event.type = WHEELDOWNMOUSE; + } + + event.val = KM_PRESS; + wm_event_add(win, &event); + + break; + } + case GHOST_kEventTimer: { + event.type = TIMER; + event.custom = EVT_DATA_TIMER; + event.customdata = customdata; + event.val = KM_NOTHING; + event.keymodifier = 0; + wm_event_add(win, &event); + + break; + } #ifdef WITH_INPUT_NDOF - case GHOST_kEventNDOFMotion: - { - event.type = NDOF_MOTION; - event.val = KM_NOTHING; - attach_ndof_data(&event, customdata); - wm_event_add(win, &event); - - CLOG_INFO(WM_LOG_HANDLERS, 1, "sending NDOF_MOTION, prev = %d %d", event.x, event.y); - break; - } - - case GHOST_kEventNDOFButton: - { - GHOST_TEventNDOFButtonData *e = customdata; - - event.type = NDOF_BUTTON_NONE + e->button; - - switch (e->action) { - case GHOST_kPress: - event.val = KM_PRESS; - break; - case GHOST_kRelease: - event.val = KM_RELEASE; - break; - } - - event.custom = 0; - event.customdata = NULL; - - wm_event_add(win, &event); - - break; - } + case GHOST_kEventNDOFMotion: { + event.type = NDOF_MOTION; + event.val = KM_NOTHING; + attach_ndof_data(&event, customdata); + wm_event_add(win, &event); + + CLOG_INFO(WM_LOG_HANDLERS, 1, "sending NDOF_MOTION, prev = %d %d", event.x, event.y); + break; + } + + case GHOST_kEventNDOFButton: { + GHOST_TEventNDOFButtonData *e = customdata; + + event.type = NDOF_BUTTON_NONE + e->button; + + switch (e->action) { + case GHOST_kPress: + event.val = KM_PRESS; + break; + case GHOST_kRelease: + event.val = KM_RELEASE; + break; + } + + event.custom = 0; + event.customdata = NULL; + + wm_event_add(win, &event); + + break; + } #endif /* WITH_INPUT_NDOF */ - case GHOST_kEventUnknown: - case GHOST_kNumEventTypes: - break; + case GHOST_kEventUnknown: + case GHOST_kNumEventTypes: + break; - case GHOST_kEventWindowDeactivate: - { - event.type = WINDEACTIVATE; - wm_event_add(win, &event); + case GHOST_kEventWindowDeactivate: { + event.type = WINDEACTIVATE; + wm_event_add(win, &event); - break; - } + break; + } #ifdef WITH_INPUT_IME - case GHOST_kEventImeCompositionStart: - { - event.val = KM_PRESS; - win->ime_data = customdata; - win->ime_data->is_ime_composing = true; - event.type = WM_IME_COMPOSITE_START; - wm_event_add(win, &event); - break; - } - case GHOST_kEventImeComposition: - { - event.val = KM_PRESS; - event.type = WM_IME_COMPOSITE_EVENT; - wm_event_add(win, &event); - break; - } - case GHOST_kEventImeCompositionEnd: - { - event.val = KM_PRESS; - if (win->ime_data) { - win->ime_data->is_ime_composing = false; - } - event.type = WM_IME_COMPOSITE_END; - wm_event_add(win, &event); - break; - } + case GHOST_kEventImeCompositionStart: { + event.val = KM_PRESS; + win->ime_data = customdata; + win->ime_data->is_ime_composing = true; + event.type = WM_IME_COMPOSITE_START; + wm_event_add(win, &event); + break; + } + case GHOST_kEventImeComposition: { + event.val = KM_PRESS; + event.type = WM_IME_COMPOSITE_EVENT; + wm_event_add(win, &event); + break; + } + case GHOST_kEventImeCompositionEnd: { + event.val = KM_PRESS; + if (win->ime_data) { + win->ime_data->is_ime_composing = false; + } + event.type = WM_IME_COMPOSITE_END; + wm_event_add(win, &event); + break; + } #endif /* WITH_INPUT_IME */ - - } + } #if 0 - WM_event_print(&event); + WM_event_print(&event); #endif } void WM_set_locked_interface(wmWindowManager *wm, bool lock) { - /* This will prevent events from being handled while interface is locked - * - * Use a "local" flag for now, because currently no other areas could - * benefit of locked interface anyway (aka using G.is_interface_locked - * wouldn't be useful anywhere outside of window manager, so let's not - * pollute global context with such an information for now). - */ - wm->is_interface_locked = lock ? 1 : 0; - - /* This will prevent drawing regions which uses non-threadsafe data. - * Currently it'll be just a 3D viewport. - * - * TODO(sergey): Make it different locked states, so different jobs - * could lock different areas of blender and allow - * interaction with others? - */ - BKE_spacedata_draw_locks(lock); + /* This will prevent events from being handled while interface is locked + * + * Use a "local" flag for now, because currently no other areas could + * benefit of locked interface anyway (aka using G.is_interface_locked + * wouldn't be useful anywhere outside of window manager, so let's not + * pollute global context with such an information for now). + */ + wm->is_interface_locked = lock ? 1 : 0; + + /* This will prevent drawing regions which uses non-threadsafe data. + * Currently it'll be just a 3D viewport. + * + * TODO(sergey): Make it different locked states, so different jobs + * could lock different areas of blender and allow + * interaction with others? + */ + BKE_spacedata_draw_locks(lock); } - #ifdef WITH_INPUT_NDOF /* -------------------------------------------------------------------- */ /* NDOF */ @@ -4555,41 +4663,40 @@ void WM_set_locked_interface(wmWindowManager *wm, bool lock) /** \name NDOF Utility Functions * \{ */ - void WM_event_ndof_pan_get(const wmNDOFMotionData *ndof, float r_pan[3], const bool use_zoom) { - int z_flag = use_zoom ? NDOF_ZOOM_INVERT : NDOF_PANZ_INVERT_AXIS; - r_pan[0] = ndof->tvec[0] * ((U.ndof_flag & NDOF_PANX_INVERT_AXIS) ? -1.0f : 1.0f); - r_pan[1] = ndof->tvec[1] * ((U.ndof_flag & NDOF_PANY_INVERT_AXIS) ? -1.0f : 1.0f); - r_pan[2] = ndof->tvec[2] * ((U.ndof_flag & z_flag) ? -1.0f : 1.0f); + int z_flag = use_zoom ? NDOF_ZOOM_INVERT : NDOF_PANZ_INVERT_AXIS; + r_pan[0] = ndof->tvec[0] * ((U.ndof_flag & NDOF_PANX_INVERT_AXIS) ? -1.0f : 1.0f); + r_pan[1] = ndof->tvec[1] * ((U.ndof_flag & NDOF_PANY_INVERT_AXIS) ? -1.0f : 1.0f); + r_pan[2] = ndof->tvec[2] * ((U.ndof_flag & z_flag) ? -1.0f : 1.0f); } void WM_event_ndof_rotate_get(const wmNDOFMotionData *ndof, float r_rot[3]) { - r_rot[0] = ndof->rvec[0] * ((U.ndof_flag & NDOF_ROTX_INVERT_AXIS) ? -1.0f : 1.0f); - r_rot[1] = ndof->rvec[1] * ((U.ndof_flag & NDOF_ROTY_INVERT_AXIS) ? -1.0f : 1.0f); - r_rot[2] = ndof->rvec[2] * ((U.ndof_flag & NDOF_ROTZ_INVERT_AXIS) ? -1.0f : 1.0f); + r_rot[0] = ndof->rvec[0] * ((U.ndof_flag & NDOF_ROTX_INVERT_AXIS) ? -1.0f : 1.0f); + r_rot[1] = ndof->rvec[1] * ((U.ndof_flag & NDOF_ROTY_INVERT_AXIS) ? -1.0f : 1.0f); + r_rot[2] = ndof->rvec[2] * ((U.ndof_flag & NDOF_ROTZ_INVERT_AXIS) ? -1.0f : 1.0f); } float WM_event_ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]) { - float angle; - angle = normalize_v3_v3(axis, ndof->rvec); + float angle; + angle = normalize_v3_v3(axis, ndof->rvec); - axis[0] = axis[0] * ((U.ndof_flag & NDOF_ROTX_INVERT_AXIS) ? -1.0f : 1.0f); - axis[1] = axis[1] * ((U.ndof_flag & NDOF_ROTY_INVERT_AXIS) ? -1.0f : 1.0f); - axis[2] = axis[2] * ((U.ndof_flag & NDOF_ROTZ_INVERT_AXIS) ? -1.0f : 1.0f); + axis[0] = axis[0] * ((U.ndof_flag & NDOF_ROTX_INVERT_AXIS) ? -1.0f : 1.0f); + axis[1] = axis[1] * ((U.ndof_flag & NDOF_ROTY_INVERT_AXIS) ? -1.0f : 1.0f); + axis[2] = axis[2] * ((U.ndof_flag & NDOF_ROTZ_INVERT_AXIS) ? -1.0f : 1.0f); - return ndof->dt * angle; + return ndof->dt * angle; } void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]) { - float axis[3]; - float angle; + float axis[3]; + float angle; - angle = WM_event_ndof_to_axis_angle(ndof, axis); - axis_angle_to_quat(q, axis, angle); + angle = WM_event_ndof_to_axis_angle(ndof, axis); + axis_angle_to_quat(q, axis, angle); } #endif /* WITH_INPUT_NDOF */ @@ -4597,44 +4704,44 @@ void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]) * to 1 if the eraser tool is being used, 0 otherwise */ float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2]) { - int erasor = 0; - float pressure = 1; - - if (tilt) { - zero_v2(tilt); - } - - if (event->tablet_data) { - const wmTabletData *wmtab = event->tablet_data; - - erasor = (wmtab->Active == EVT_TABLET_ERASER); - if (wmtab->Active != EVT_TABLET_NONE) { - pressure = wmtab->Pressure; - if (tilt) { - tilt[0] = wmtab->Xtilt; - tilt[1] = wmtab->Ytilt; - } - } - } - - if (pen_flip) { - (*pen_flip) = erasor; - } - - return pressure; + int erasor = 0; + float pressure = 1; + + if (tilt) { + zero_v2(tilt); + } + + if (event->tablet_data) { + const wmTabletData *wmtab = event->tablet_data; + + erasor = (wmtab->Active == EVT_TABLET_ERASER); + if (wmtab->Active != EVT_TABLET_NONE) { + pressure = wmtab->Pressure; + if (tilt) { + tilt[0] = wmtab->Xtilt; + tilt[1] = wmtab->Ytilt; + } + } + } + + if (pen_flip) { + (*pen_flip) = erasor; + } + + return pressure; } bool WM_event_is_tablet(const struct wmEvent *event) { - return (event->tablet_data) ? true : false; + return (event->tablet_data) ? true : false; } #ifdef WITH_INPUT_IME /* most os using ctrl/oskey + space to switch ime, avoid added space */ bool WM_event_is_ime_switch(const struct wmEvent *event) { - return event->val == KM_PRESS && event->type == SPACEKEY && - (event->ctrl || event->oskey || event->shift || event->alt); + return event->val == KM_PRESS && event->type == SPACEKEY && + (event->ctrl || event->oskey || event->shift || event->alt); } #endif @@ -4642,45 +4749,46 @@ bool WM_event_is_ime_switch(const struct wmEvent *event) wmKeyMap *WM_event_get_keymap_from_handler(wmWindowManager *wm, wmEventHandler_Keymap *handler) { - wmKeyMap *keymap; - if (handler->dynamic.keymap_fn != NULL) { - keymap = handler->dynamic.keymap_fn(wm, handler); - BLI_assert(handler->keymap == NULL); - } - else { - keymap = WM_keymap_active(wm, handler->keymap); - BLI_assert(keymap != NULL); - } - return keymap; + wmKeyMap *keymap; + if (handler->dynamic.keymap_fn != NULL) { + keymap = handler->dynamic.keymap_fn(wm, handler); + BLI_assert(handler->keymap == NULL); + } + else { + keymap = WM_keymap_active(wm, handler->keymap); + BLI_assert(keymap != NULL); + } + return keymap; } -static wmKeyMapItem *wm_kmi_from_event( - bContext *C, wmWindowManager *wm, - ListBase *handlers, const wmEvent *event) +static wmKeyMapItem *wm_kmi_from_event(bContext *C, + wmWindowManager *wm, + ListBase *handlers, + const wmEvent *event) { - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { - /* during this loop, ui handlers for nested menus can tag multiple handlers free */ - if (handler_base->flag & WM_HANDLER_DO_FREE) { - /* pass */ - } - else if (handler_boundbox_test(handler_base, event)) { /* optional boundbox */ - if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { - wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - if (keymap && WM_keymap_poll(C, keymap)) { - for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (wm_eventmatch(event, kmi)) { - wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0); - if (WM_operator_poll_context(C, ot, WM_OP_INVOKE_DEFAULT)) { - return kmi; - } - } - } - } - } - } - } - return NULL; + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { + /* during this loop, ui handlers for nested menus can tag multiple handlers free */ + if (handler_base->flag & WM_HANDLER_DO_FREE) { + /* pass */ + } + else if (handler_boundbox_test(handler_base, event)) { /* optional boundbox */ + if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { + wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; + wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); + if (keymap && WM_keymap_poll(C, keymap)) { + for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (wm_eventmatch(event, kmi)) { + wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0); + if (WM_operator_poll_context(C, ot, WM_OP_INVOKE_DEFAULT)) { + return kmi; + } + } + } + } + } + } + } + return NULL; } /* -------------------------------------------------------------------- */ @@ -4693,50 +4801,52 @@ static wmKeyMapItem *wm_kmi_from_event( /** State storage to detect changes between calls to refresh the information. */ struct CursorKeymapInfo_State { - struct { - short shift, ctrl, alt, oskey; - } modifiers; - short space_type; - short region_type; - /* Never use, just compare memory for changes. */ - bToolRef tref; + struct { + short shift, ctrl, alt, oskey; + } modifiers; + short space_type; + short region_type; + /* Never use, just compare memory for changes. */ + bToolRef tref; }; struct CursorKeymapInfo { - /* 0: mouse button index - * 1: event type (click/press, drag) - * 2: text. - */ - char text[3][2][128]; - wmEvent state_event; - struct CursorKeymapInfo_State state; + /* 0: mouse button index + * 1: event type (click/press, drag) + * 2: text. + */ + char text[3][2][128]; + wmEvent state_event; + struct CursorKeymapInfo_State state; }; -static void wm_event_cursor_store( - struct CursorKeymapInfo_State *state, - const wmEvent *event, - short space_type, short region_type, - const bToolRef *tref) +static void wm_event_cursor_store(struct CursorKeymapInfo_State *state, + const wmEvent *event, + short space_type, + short region_type, + const bToolRef *tref) { - state->modifiers.shift = event->shift; - state->modifiers.ctrl = event->ctrl; - state->modifiers.alt = event->alt; - state->modifiers.oskey = event->oskey; - state->space_type = space_type; - state->region_type = region_type; - state->tref = tref ? *tref : (bToolRef){0}; + state->modifiers.shift = event->shift; + state->modifiers.ctrl = event->ctrl; + state->modifiers.alt = event->alt; + state->modifiers.oskey = event->oskey; + state->space_type = space_type; + state->region_type = region_type; + state->tref = tref ? *tref : (bToolRef){0}; } -const char *WM_window_cursor_keymap_status_get(const wmWindow *win, int button_index, int type_index) +const char *WM_window_cursor_keymap_status_get(const wmWindow *win, + int button_index, + int type_index) { - if (win->cursor_keymap_status != NULL) { - struct CursorKeymapInfo *cd = win->cursor_keymap_status; - const char *msg = cd->text[button_index][type_index]; - if (*msg) { - return msg; - } - } - return NULL; + if (win->cursor_keymap_status != NULL) { + struct CursorKeymapInfo *cd = win->cursor_keymap_status; + const char *msg = cd->text[button_index][type_index]; + if (*msg) { + return msg; + } + } + return NULL; } /** @@ -4745,166 +4855,165 @@ const char *WM_window_cursor_keymap_status_get(const wmWindow *win, int button_i */ ScrArea *WM_window_status_area_find(wmWindow *win, bScreen *screen) { - if (screen->state == SCREENFULL) { - return NULL; - } - ScrArea *sa_statusbar = NULL; - for (ScrArea *sa = win->global_areas.areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_STATUSBAR) { - sa_statusbar = sa; - break; - } - } - return sa_statusbar; + if (screen->state == SCREENFULL) { + return NULL; + } + ScrArea *sa_statusbar = NULL; + for (ScrArea *sa = win->global_areas.areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_STATUSBAR) { + sa_statusbar = sa; + break; + } + } + return sa_statusbar; } void WM_window_status_area_tag_redraw(wmWindow *win) { - bScreen *sc = WM_window_get_active_screen(win); - ScrArea *sa = WM_window_status_area_find(win, sc); - if (sa != NULL) { - ED_area_tag_redraw(sa); - } + bScreen *sc = WM_window_get_active_screen(win); + ScrArea *sa = WM_window_status_area_find(win, sc); + if (sa != NULL) { + ED_area_tag_redraw(sa); + } } void WM_window_cursor_keymap_status_refresh(bContext *C, wmWindow *win) { - bScreen *screen = WM_window_get_active_screen(win); - ScrArea *sa_statusbar = WM_window_status_area_find(win, screen); - if (sa_statusbar == NULL) { - MEM_SAFE_FREE(win->cursor_keymap_status); - return; - } - - struct CursorKeymapInfo *cd; - if (UNLIKELY(win->cursor_keymap_status == NULL)) { - win->cursor_keymap_status = MEM_callocN(sizeof(struct CursorKeymapInfo), __func__); - } - cd = win->cursor_keymap_status; - - /* Detect unchanged state (early exit). */ - if (memcmp(&cd->state_event, win->eventstate, sizeof(wmEvent)) == 0) { - return; - } - - /* Now perform more comprehensive check, - * still keep this fast since it happens on mouse-move. */ - struct CursorKeymapInfo cd_prev = *((struct CursorKeymapInfo *)win->cursor_keymap_status); - cd->state_event = *win->eventstate; - - /* Find active region and associated area. */ - ARegion *ar = screen->active_region; - if (ar == NULL) { - return; - } - - ScrArea *sa = NULL; - ED_screen_areas_iter(win, screen, sa_iter) { - if (BLI_findindex(&sa_iter->regionbase, ar) != -1) { - sa = sa_iter; - break; - } - } - if (sa == NULL) { - return; - } - - /* Keep as-is. */ - if (ELEM(sa->spacetype, SPACE_STATUSBAR, SPACE_TOPBAR)) { - return; - } - if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER, RGN_TYPE_TEMPORARY, RGN_TYPE_HUD)) { - return; - } - /* Fallback to window. */ - if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS)) { - ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - } - - /* Detect changes to the state. */ - { - bToolRef *tref = NULL; - if ((ar->regiontype == RGN_TYPE_WINDOW) && - ((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK)) - { - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - WorkSpace *workspace = WM_window_get_active_workspace(win); - const bToolKey tkey = { - .space_type = sa->spacetype, - .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), - }; - tref = WM_toolsystem_ref_find(workspace, &tkey); - } - wm_event_cursor_store(&cd->state, win->eventstate, sa->spacetype, ar->regiontype, tref); - if (memcmp(&cd->state, &cd_prev.state, sizeof(cd->state)) == 0) { - return; - } - } - - /* Changed context found, detect changes to keymap and refresh the status bar. */ - const struct { - int button_index; - int type_index; /* 0: press or click, 1: drag. */ - int event_type; - int event_value; - } event_data[] = { - {0, 0, LEFTMOUSE, KM_PRESS}, - {0, 0, LEFTMOUSE, KM_CLICK}, - {0, 1, EVT_TWEAK_L, KM_ANY}, - - {1, 0, MIDDLEMOUSE, KM_PRESS}, - {1, 0, MIDDLEMOUSE, KM_CLICK}, - {1, 1, EVT_TWEAK_M, KM_ANY}, - - {2, 0, RIGHTMOUSE, KM_PRESS}, - {2, 0, RIGHTMOUSE, KM_CLICK}, - {2, 1, EVT_TWEAK_R, KM_ANY}, - }; - - for (int button_index = 0; button_index < 3; button_index++) { - cd->text[button_index][0][0] = '\0'; - cd->text[button_index][1][0] = '\0'; - } - - CTX_wm_window_set(C, win); - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); - - ListBase *handlers[] = { - &ar->handlers, - &sa->handlers, - &win->handlers, - }; - - wmWindowManager *wm = CTX_wm_manager(C); - for (int data_index = 0; data_index < ARRAY_SIZE(event_data); data_index++) { - const int button_index = event_data[data_index].button_index; - const int type_index = event_data[data_index].type_index; - if (cd->text[button_index][type_index][0] != 0) { - continue; - } - wmEvent test_event = *win->eventstate; - test_event.type = event_data[data_index].event_type; - test_event.val = event_data[data_index].event_value; - wm_eventemulation(&test_event, true); - wmKeyMapItem *kmi = NULL; - for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) { - kmi = wm_kmi_from_event(C, wm, handlers[handler_index], &test_event); - if (kmi) { - break; - } - } - if (kmi) { - wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0); - STRNCPY(cd->text[button_index][type_index], ot ? ot->name : kmi->idname); - } - } - - if (memcmp(&cd_prev.text, &cd->text, sizeof(cd_prev.text)) != 0) { - ED_area_tag_redraw(sa_statusbar); - } - - CTX_wm_window_set(C, NULL); + bScreen *screen = WM_window_get_active_screen(win); + ScrArea *sa_statusbar = WM_window_status_area_find(win, screen); + if (sa_statusbar == NULL) { + MEM_SAFE_FREE(win->cursor_keymap_status); + return; + } + + struct CursorKeymapInfo *cd; + if (UNLIKELY(win->cursor_keymap_status == NULL)) { + win->cursor_keymap_status = MEM_callocN(sizeof(struct CursorKeymapInfo), __func__); + } + cd = win->cursor_keymap_status; + + /* Detect unchanged state (early exit). */ + if (memcmp(&cd->state_event, win->eventstate, sizeof(wmEvent)) == 0) { + return; + } + + /* Now perform more comprehensive check, + * still keep this fast since it happens on mouse-move. */ + struct CursorKeymapInfo cd_prev = *((struct CursorKeymapInfo *)win->cursor_keymap_status); + cd->state_event = *win->eventstate; + + /* Find active region and associated area. */ + ARegion *ar = screen->active_region; + if (ar == NULL) { + return; + } + + ScrArea *sa = NULL; + ED_screen_areas_iter(win, screen, sa_iter) + { + if (BLI_findindex(&sa_iter->regionbase, ar) != -1) { + sa = sa_iter; + break; + } + } + if (sa == NULL) { + return; + } + + /* Keep as-is. */ + if (ELEM(sa->spacetype, SPACE_STATUSBAR, SPACE_TOPBAR)) { + return; + } + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER, RGN_TYPE_TEMPORARY, RGN_TYPE_HUD)) { + return; + } + /* Fallback to window. */ + if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS)) { + ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + } + + /* Detect changes to the state. */ + { + bToolRef *tref = NULL; + if ((ar->regiontype == RGN_TYPE_WINDOW) && ((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK)) { + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + WorkSpace *workspace = WM_window_get_active_workspace(win); + const bToolKey tkey = { + .space_type = sa->spacetype, + .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), + }; + tref = WM_toolsystem_ref_find(workspace, &tkey); + } + wm_event_cursor_store(&cd->state, win->eventstate, sa->spacetype, ar->regiontype, tref); + if (memcmp(&cd->state, &cd_prev.state, sizeof(cd->state)) == 0) { + return; + } + } + + /* Changed context found, detect changes to keymap and refresh the status bar. */ + const struct { + int button_index; + int type_index; /* 0: press or click, 1: drag. */ + int event_type; + int event_value; + } event_data[] = { + {0, 0, LEFTMOUSE, KM_PRESS}, + {0, 0, LEFTMOUSE, KM_CLICK}, + {0, 1, EVT_TWEAK_L, KM_ANY}, + + {1, 0, MIDDLEMOUSE, KM_PRESS}, + {1, 0, MIDDLEMOUSE, KM_CLICK}, + {1, 1, EVT_TWEAK_M, KM_ANY}, + + {2, 0, RIGHTMOUSE, KM_PRESS}, + {2, 0, RIGHTMOUSE, KM_CLICK}, + {2, 1, EVT_TWEAK_R, KM_ANY}, + }; + + for (int button_index = 0; button_index < 3; button_index++) { + cd->text[button_index][0][0] = '\0'; + cd->text[button_index][1][0] = '\0'; + } + + CTX_wm_window_set(C, win); + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + + ListBase *handlers[] = { + &ar->handlers, + &sa->handlers, + &win->handlers, + }; + + wmWindowManager *wm = CTX_wm_manager(C); + for (int data_index = 0; data_index < ARRAY_SIZE(event_data); data_index++) { + const int button_index = event_data[data_index].button_index; + const int type_index = event_data[data_index].type_index; + if (cd->text[button_index][type_index][0] != 0) { + continue; + } + wmEvent test_event = *win->eventstate; + test_event.type = event_data[data_index].event_type; + test_event.val = event_data[data_index].event_value; + wm_eventemulation(&test_event, true); + wmKeyMapItem *kmi = NULL; + for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) { + kmi = wm_kmi_from_event(C, wm, handlers[handler_index], &test_event); + if (kmi) { + break; + } + } + if (kmi) { + wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0); + STRNCPY(cd->text[button_index][type_index], ot ? ot->name : kmi->idname); + } + } + + if (memcmp(&cd_prev.text, &cd->text, sizeof(cd_prev.text)) != 0) { + ED_area_tag_redraw(sa_statusbar); + } + + CTX_wm_window_set(C, NULL); } /** \} */ @@ -4914,86 +5023,83 @@ void WM_window_cursor_keymap_status_refresh(bContext *C, wmWindow *win) * * \{ */ -bool WM_window_modal_keymap_status_draw( - bContext *UNUSED(C), wmWindow *win, - uiLayout *layout) +bool WM_window_modal_keymap_status_draw(bContext *UNUSED(C), wmWindow *win, uiLayout *layout) { - wmKeyMap *keymap = NULL; - wmOperator *op = NULL; - LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { - if (handler_base->type == WM_HANDLER_TYPE_OP) { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - if (handler->op != NULL) { - /* 'handler->keymap' could be checked too, seems not to be used. */ - wmKeyMap *keymap_test = handler->op->type->modalkeymap; - if (keymap_test && keymap_test->modal_items) { - keymap = keymap_test; - op = handler->op; - break; - } - } - } - } - if (keymap == NULL || keymap->modal_items == NULL) { - return false; - } - const EnumPropertyItem *items = keymap->modal_items; - - uiLayout *row = uiLayoutRow(layout, true); - for (int i = 0; items[i].identifier; i++) { - if (!items[i].identifier[0]) { - continue; - } - if ((keymap->poll_modal_item != NULL) && - (keymap->poll_modal_item(op, items[i].value) == false)) - { - continue; - } - - bool show_text = true; - - { - /* warning: O(n^2) */ - wmKeyMapItem *kmi = NULL; - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (kmi->propvalue == items[i].value) { - break; - } - } - if (kmi != NULL) { - if (kmi->val == KM_RELEASE) { - /* Assume release events just disable something which was toggled on. */ - continue; - } - int icon_mod[4]; + wmKeyMap *keymap = NULL; + wmOperator *op = NULL; + LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { + if (handler_base->type == WM_HANDLER_TYPE_OP) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + if (handler->op != NULL) { + /* 'handler->keymap' could be checked too, seems not to be used. */ + wmKeyMap *keymap_test = handler->op->type->modalkeymap; + if (keymap_test && keymap_test->modal_items) { + keymap = keymap_test; + op = handler->op; + break; + } + } + } + } + if (keymap == NULL || keymap->modal_items == NULL) { + return false; + } + const EnumPropertyItem *items = keymap->modal_items; + + uiLayout *row = uiLayoutRow(layout, true); + for (int i = 0; items[i].identifier; i++) { + if (!items[i].identifier[0]) { + continue; + } + if ((keymap->poll_modal_item != NULL) && + (keymap->poll_modal_item(op, items[i].value) == false)) { + continue; + } + + bool show_text = true; + + { + /* warning: O(n^2) */ + wmKeyMapItem *kmi = NULL; + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (kmi->propvalue == items[i].value) { + break; + } + } + if (kmi != NULL) { + if (kmi->val == KM_RELEASE) { + /* Assume release events just disable something which was toggled on. */ + continue; + } + int icon_mod[4]; #ifdef WITH_HEADLESS - int icon = 0; + int icon = 0; #else - int icon = UI_icon_from_keymap_item(kmi, icon_mod); + int icon = UI_icon_from_keymap_item(kmi, icon_mod); #endif - if (icon != 0) { - for (int j = 0; j < ARRAY_SIZE(icon_mod) && icon_mod[j]; j++) { - uiItemL(row, "", icon_mod[j]); - } - uiItemL(row, items[i].name, icon); - show_text = false; - } - } - } - if (show_text) { - char buf[UI_MAX_DRAW_STR]; - int available_len = sizeof(buf); - char *p = buf; - WM_modalkeymap_operator_items_to_string_buf( - op->type, items[i].value, true, UI_MAX_SHORTCUT_STR, &available_len, &p); - p -= 1; - if (p > buf) { - BLI_snprintf(p, available_len, ": %s", items[i].name); - uiItemL(row, buf, 0); - } - } - } - return true; + if (icon != 0) { + for (int j = 0; j < ARRAY_SIZE(icon_mod) && icon_mod[j]; j++) { + uiItemL(row, "", icon_mod[j]); + } + uiItemL(row, items[i].name, icon); + show_text = false; + } + } + } + if (show_text) { + char buf[UI_MAX_DRAW_STR]; + int available_len = sizeof(buf); + char *p = buf; + WM_modalkeymap_operator_items_to_string_buf( + op->type, items[i].value, true, UI_MAX_SHORTCUT_STR, &available_len, &p); + p -= 1; + if (p > buf) { + BLI_snprintf(p, available_len, ": %s", items[i].name); + uiItemL(row, buf, 0); + } + } + } + return true; } /** \} */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index abea0571a2c..a4e059effb4 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -23,7 +23,6 @@ * User level access for blend file read/write, file-history and userprefs (including relevant operators). */ - /* placed up here because of crappy * winsock stuff. */ @@ -34,13 +33,13 @@ #include "zlib.h" /* wm_read_exotic() */ #ifdef WIN32 - /* Need to include windows.h so _WIN32_IE is defined. */ +/* Need to include windows.h so _WIN32_IE is defined. */ # include <windows.h> # ifndef _WIN32_IE - /* Minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already. */ +/* Minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already. */ # define _WIN32_IE 0x0400 # endif - /* For SHGetSpecialFolderPath, has to be done before BLI_winstuff +/* For SHGetSpecialFolderPath, has to be done before BLI_winstuff * because 'near' is disabled through BLI_windstuff */ # include <shlobj.h> # include "BLI_winstuff.h" @@ -87,7 +86,7 @@ #include "BLO_readfile.h" #include "BLO_writefile.h" -#include "BLO_undofile.h" /* to save from an undo memfile */ +#include "BLO_undofile.h" /* to save from an undo memfile */ #include "RNA_access.h" #include "RNA_define.h" @@ -116,7 +115,7 @@ #include "RE_engine.h" #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif #include "DEG_depsgraph.h" @@ -136,7 +135,6 @@ static void wm_history_file_free(RecentFile *recent); static void wm_history_file_update(void); static void wm_history_file_write(void); - /* To be able to read files without windows closing, opening, moving * we try to prepare for worst case: * - active window gets active screen from file @@ -145,161 +143,166 @@ static void wm_history_file_write(void); */ static void wm_window_match_init(bContext *C, ListBase *wmlist) { - wmWindowManager *wm; - wmWindow *win, *active_win; - - *wmlist = G_MAIN->wm; - BLI_listbase_clear(&G_MAIN->wm); + wmWindowManager *wm; + wmWindow *win, *active_win; + + *wmlist = G_MAIN->wm; + BLI_listbase_clear(&G_MAIN->wm); - active_win = CTX_wm_window(C); + active_win = CTX_wm_window(C); + + /* first wrap up running stuff */ + /* code copied from wm_init_exit.c */ + for (wm = wmlist->first; wm; wm = wm->id.next) { - /* first wrap up running stuff */ - /* code copied from wm_init_exit.c */ - for (wm = wmlist->first; wm; wm = wm->id.next) { + WM_jobs_kill_all(wm); - WM_jobs_kill_all(wm); + for (win = wm->windows.first; win; win = win->next) { - for (win = wm->windows.first; win; win = win->next) { + CTX_wm_window_set(C, win); /* needed by operator close callbacks */ + WM_event_remove_handlers(C, &win->handlers); + WM_event_remove_handlers(C, &win->modalhandlers); + ED_screen_exit(C, win, WM_window_get_active_screen(win)); + } + } - CTX_wm_window_set(C, win); /* needed by operator close callbacks */ - WM_event_remove_handlers(C, &win->handlers); - WM_event_remove_handlers(C, &win->modalhandlers); - ED_screen_exit(C, win, WM_window_get_active_screen(win)); - } - } + /* reset active window */ + CTX_wm_window_set(C, active_win); - /* reset active window */ - CTX_wm_window_set(C, active_win); + /* XXX Hack! We have to clear context menu here, because removing all modalhandlers above frees the active menu + * (at least, in the 'startup splash' case), causing use-after-free error in later handling of the button + * callbacks in UI code (see ui_apply_but_funcs_after()). + * Tried solving this by always NULL-ing context's menu when setting wm/win/etc., but it broke popups refreshing + * (see T47632), so for now just handling this specific case here. */ + CTX_wm_menu_set(C, NULL); - /* XXX Hack! We have to clear context menu here, because removing all modalhandlers above frees the active menu - * (at least, in the 'startup splash' case), causing use-after-free error in later handling of the button - * callbacks in UI code (see ui_apply_but_funcs_after()). - * Tried solving this by always NULL-ing context's menu when setting wm/win/etc., but it broke popups refreshing - * (see T47632), so for now just handling this specific case here. */ - CTX_wm_menu_set(C, NULL); - - ED_editors_exit(G_MAIN, true); + ED_editors_exit(G_MAIN, true); } -static void wm_window_substitute_old(wmWindowManager *oldwm, wmWindowManager *wm, wmWindow *oldwin, wmWindow *win) +static void wm_window_substitute_old(wmWindowManager *oldwm, + wmWindowManager *wm, + wmWindow *oldwin, + wmWindow *win) { - win->ghostwin = oldwin->ghostwin; - win->gpuctx = oldwin->gpuctx; - win->active = oldwin->active; - if (win->active) { - wm->winactive = win; - } - if (oldwm->windrawable == oldwin) { - oldwm->windrawable = NULL; - wm->windrawable = win; - } - - /* File loading in background mode still calls this. */ - if (!G.background) { - /* Pointer back. */ - GHOST_SetWindowUserData(win->ghostwin, win); - } - - oldwin->ghostwin = NULL; - oldwin->gpuctx = NULL; + win->ghostwin = oldwin->ghostwin; + win->gpuctx = oldwin->gpuctx; + win->active = oldwin->active; + if (win->active) { + wm->winactive = win; + } + if (oldwm->windrawable == oldwin) { + oldwm->windrawable = NULL; + wm->windrawable = win; + } + + /* File loading in background mode still calls this. */ + if (!G.background) { + /* Pointer back. */ + GHOST_SetWindowUserData(win->ghostwin, win); + } + + oldwin->ghostwin = NULL; + oldwin->gpuctx = NULL; - win->eventstate = oldwin->eventstate; - oldwin->eventstate = NULL; + win->eventstate = oldwin->eventstate; + oldwin->eventstate = NULL; - /* ensure proper screen rescaling */ - win->sizex = oldwin->sizex; - win->sizey = oldwin->sizey; - win->posx = oldwin->posx; - win->posy = oldwin->posy; + /* ensure proper screen rescaling */ + win->sizex = oldwin->sizex; + win->sizey = oldwin->sizey; + win->posx = oldwin->posx; + win->posy = oldwin->posy; } -static void wm_window_match_keep_current_wm( - const bContext *C, ListBase *current_wm_list, - const bool load_ui, - ListBase *r_new_wm_list) +static void wm_window_match_keep_current_wm(const bContext *C, + ListBase *current_wm_list, + const bool load_ui, + ListBase *r_new_wm_list) { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = current_wm_list->first; - bScreen *screen = NULL; - - /* match oldwm to new dbase, only old files */ - wm->initialized &= ~WM_WINDOW_IS_INITIALIZED; - - /* when loading without UI, no matching needed */ - if (load_ui && (screen = CTX_wm_screen(C))) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { - WorkSpace *workspace; - - BKE_workspace_layout_find_global(bmain, screen, &workspace); - BKE_workspace_active_set(win->workspace_hook, workspace); - win->scene = CTX_data_scene(C); - - /* all windows get active screen from file */ - if (screen->winid == 0) { - WM_window_set_active_screen(win, workspace, screen); - } - else { - WorkSpaceLayout *layout_old = WM_window_get_active_layout(win); - WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(bmain, workspace, layout_old, win); - - WM_window_set_active_layout(win, workspace, layout_new); - } + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = current_wm_list->first; + bScreen *screen = NULL; - bScreen *win_screen = WM_window_get_active_screen(win); - win_screen->winid = win->winid; - } - } + /* match oldwm to new dbase, only old files */ + wm->initialized &= ~WM_WINDOW_IS_INITIALIZED; - *r_new_wm_list = *current_wm_list; -} + /* when loading without UI, no matching needed */ + if (load_ui && (screen = CTX_wm_screen(C))) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { + WorkSpace *workspace; -static void wm_window_match_replace_by_file_wm( - bContext *C, ListBase *current_wm_list, ListBase *readfile_wm_list, - ListBase *r_new_wm_list) -{ - wmWindowManager *oldwm = current_wm_list->first; - wmWindowManager *wm = readfile_wm_list->first; /* will become our new WM */ - bool has_match = false; + BKE_workspace_layout_find_global(bmain, screen, &workspace); + BKE_workspace_active_set(win->workspace_hook, workspace); + win->scene = CTX_data_scene(C); - /* this code could move to setup_appdata */ - - /* preserve key configurations in new wm, to preserve their keymaps */ - wm->keyconfigs = oldwm->keyconfigs; - wm->addonconf = oldwm->addonconf; - wm->defaultconf = oldwm->defaultconf; - wm->userconf = oldwm->userconf; + /* all windows get active screen from file */ + if (screen->winid == 0) { + WM_window_set_active_screen(win, workspace, screen); + } + else { + WorkSpaceLayout *layout_old = WM_window_get_active_layout(win); + WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate( + bmain, workspace, layout_old, win); - BLI_listbase_clear(&oldwm->keyconfigs); - oldwm->addonconf = NULL; - oldwm->defaultconf = NULL; - oldwm->userconf = NULL; + WM_window_set_active_layout(win, workspace, layout_new); + } - /* ensure making new keymaps and set space types */ - wm->initialized = 0; - wm->winactive = NULL; + bScreen *win_screen = WM_window_get_active_screen(win); + win_screen->winid = win->winid; + } + } + + *r_new_wm_list = *current_wm_list; +} - /* Clearing drawable of before deleting any context - * to avoid clearing the wrong wm. */ - wm_window_clear_drawable(oldwm); - - /* only first wm in list has ghostwins */ - for (wmWindow *win = wm->windows.first; win; win = win->next) { - for (wmWindow *oldwin = oldwm->windows.first; oldwin; oldwin = oldwin->next) { - if (oldwin->winid == win->winid) { - has_match = true; +static void wm_window_match_replace_by_file_wm(bContext *C, + ListBase *current_wm_list, + ListBase *readfile_wm_list, + ListBase *r_new_wm_list) +{ + wmWindowManager *oldwm = current_wm_list->first; + wmWindowManager *wm = readfile_wm_list->first; /* will become our new WM */ + bool has_match = false; + + /* this code could move to setup_appdata */ + + /* preserve key configurations in new wm, to preserve their keymaps */ + wm->keyconfigs = oldwm->keyconfigs; + wm->addonconf = oldwm->addonconf; + wm->defaultconf = oldwm->defaultconf; + wm->userconf = oldwm->userconf; + + BLI_listbase_clear(&oldwm->keyconfigs); + oldwm->addonconf = NULL; + oldwm->defaultconf = NULL; + oldwm->userconf = NULL; + + /* ensure making new keymaps and set space types */ + wm->initialized = 0; + wm->winactive = NULL; + + /* Clearing drawable of before deleting any context + * to avoid clearing the wrong wm. */ + wm_window_clear_drawable(oldwm); + + /* only first wm in list has ghostwins */ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + for (wmWindow *oldwin = oldwm->windows.first; oldwin; oldwin = oldwin->next) { + if (oldwin->winid == win->winid) { + has_match = true; - wm_window_substitute_old(oldwm, wm, oldwin, win); - } - } - } - /* make sure at least one window is kept open so we don't lose the context, check T42303 */ - if (!has_match) { - wm_window_substitute_old(oldwm, wm, oldwm->windows.first, wm->windows.first); - } + wm_window_substitute_old(oldwm, wm, oldwin, win); + } + } + } + /* make sure at least one window is kept open so we don't lose the context, check T42303 */ + if (!has_match) { + wm_window_substitute_old(oldwm, wm, oldwm->windows.first, wm->windows.first); + } - wm_close_and_free_all(C, current_wm_list); + wm_close_and_free_all(C, current_wm_list); - *r_new_wm_list = *readfile_wm_list; + *r_new_wm_list = *readfile_wm_list; } /** @@ -311,383 +314,380 @@ static void wm_window_match_replace_by_file_wm( * * \param r_new_wm_list: Return argument for the wm list to be used from now on. */ -static void wm_window_match_do( - bContext *C, - ListBase *current_wm_list, ListBase *readfile_wm_list, - ListBase *r_new_wm_list) -{ - if (BLI_listbase_is_empty(current_wm_list)) { - /* case 1 */ - if (BLI_listbase_is_empty(readfile_wm_list)) { - Main *bmain = CTX_data_main(C); - /* Neither current, no newly read file have a WM -> add the default one. */ - wm_add_default(bmain, C); - *r_new_wm_list = bmain->wm; - } - /* case 2 */ - else { - *r_new_wm_list = *readfile_wm_list; - } - } - else { - /* case 3 */ - if (BLI_listbase_is_empty(readfile_wm_list)) { - /* We've read file without wm, keep current one entirely alive. - * Happens when reading pre 2.5 files (no WM back then) */ - wm_window_match_keep_current_wm(C, current_wm_list, (G.fileflags & G_FILE_NO_UI) == 0, r_new_wm_list); - } - /* case 4 */ - else { - wm_window_match_replace_by_file_wm(C, current_wm_list, readfile_wm_list, r_new_wm_list); - } - } +static void wm_window_match_do(bContext *C, + ListBase *current_wm_list, + ListBase *readfile_wm_list, + ListBase *r_new_wm_list) +{ + if (BLI_listbase_is_empty(current_wm_list)) { + /* case 1 */ + if (BLI_listbase_is_empty(readfile_wm_list)) { + Main *bmain = CTX_data_main(C); + /* Neither current, no newly read file have a WM -> add the default one. */ + wm_add_default(bmain, C); + *r_new_wm_list = bmain->wm; + } + /* case 2 */ + else { + *r_new_wm_list = *readfile_wm_list; + } + } + else { + /* case 3 */ + if (BLI_listbase_is_empty(readfile_wm_list)) { + /* We've read file without wm, keep current one entirely alive. + * Happens when reading pre 2.5 files (no WM back then) */ + wm_window_match_keep_current_wm( + C, current_wm_list, (G.fileflags & G_FILE_NO_UI) == 0, r_new_wm_list); + } + /* case 4 */ + else { + wm_window_match_replace_by_file_wm(C, current_wm_list, readfile_wm_list, r_new_wm_list); + } + } } /* in case UserDef was read, we re-initialize all, and do versioning */ static void wm_init_userdef(Main *bmain, const bool read_userdef_from_memory) { - /* versioning is here */ - UI_init_userdef(bmain); + /* versioning is here */ + UI_init_userdef(bmain); - MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024); - BKE_sound_init(bmain); + MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024); + BKE_sound_init(bmain); - /* needed so loading a file from the command line respects user-pref [#26156] */ - SET_FLAG_FROM_TEST(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI); + /* needed so loading a file from the command line respects user-pref [#26156] */ + SET_FLAG_FROM_TEST(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI); - /* set the python auto-execute setting from user prefs */ - /* enabled by default, unless explicitly enabled in the command line which overrides */ - if ((G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) == 0) { - SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC); - } + /* set the python auto-execute setting from user prefs */ + /* enabled by default, unless explicitly enabled in the command line which overrides */ + if ((G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) == 0) { + SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC); + } - /* avoid re-saving for every small change to our prefs, allow overrides */ - if (read_userdef_from_memory) { - BLO_update_defaults_userpref_blend(); - } + /* avoid re-saving for every small change to our prefs, allow overrides */ + if (read_userdef_from_memory) { + BLO_update_defaults_userpref_blend(); + } - /* update tempdir from user preferences */ - BKE_tempdir_init(U.tempdir); + /* update tempdir from user preferences */ + BKE_tempdir_init(U.tempdir); } - - /* return codes */ -#define BKE_READ_EXOTIC_FAIL_PATH -3 /* file format is not supported */ -#define BKE_READ_EXOTIC_FAIL_FORMAT -2 /* file format is not supported */ -#define BKE_READ_EXOTIC_FAIL_OPEN -1 /* Can't open the file */ -#define BKE_READ_EXOTIC_OK_BLEND 0 /* .blend file */ +#define BKE_READ_EXOTIC_FAIL_PATH -3 /* file format is not supported */ +#define BKE_READ_EXOTIC_FAIL_FORMAT -2 /* file format is not supported */ +#define BKE_READ_EXOTIC_FAIL_OPEN -1 /* Can't open the file */ +#define BKE_READ_EXOTIC_OK_BLEND 0 /* .blend file */ #if 0 -#define BKE_READ_EXOTIC_OK_OTHER 1 /* other supported formats */ +# define BKE_READ_EXOTIC_OK_OTHER 1 /* other supported formats */ #endif - /* intended to check for non-blender formats but for now it only reads blends */ static int wm_read_exotic(const char *name) { - int len; - gzFile gzfile; - char header[7]; - int retval; - - /* make sure we're not trying to read a directory.... */ - - len = strlen(name); - if (len > 0 && ELEM(name[len - 1], '/', '\\')) { - retval = BKE_READ_EXOTIC_FAIL_PATH; - } - else { - gzfile = BLI_gzopen(name, "rb"); - if (gzfile == NULL) { - retval = BKE_READ_EXOTIC_FAIL_OPEN; - } - else { - len = gzread(gzfile, header, sizeof(header)); - gzclose(gzfile); - if (len == sizeof(header) && STREQLEN(header, "BLENDER", 7)) { - retval = BKE_READ_EXOTIC_OK_BLEND; - } - else { - /* We may want to support loading other file formats - * from their header bytes or file extension. - * This used to be supported in the code below and may be added - * back at some point. */ + int len; + gzFile gzfile; + char header[7]; + int retval; + + /* make sure we're not trying to read a directory.... */ + + len = strlen(name); + if (len > 0 && ELEM(name[len - 1], '/', '\\')) { + retval = BKE_READ_EXOTIC_FAIL_PATH; + } + else { + gzfile = BLI_gzopen(name, "rb"); + if (gzfile == NULL) { + retval = BKE_READ_EXOTIC_FAIL_OPEN; + } + else { + len = gzread(gzfile, header, sizeof(header)); + gzclose(gzfile); + if (len == sizeof(header) && STREQLEN(header, "BLENDER", 7)) { + retval = BKE_READ_EXOTIC_OK_BLEND; + } + else { + /* We may want to support loading other file formats + * from their header bytes or file extension. + * This used to be supported in the code below and may be added + * back at some point. */ #if 0 - WM_cursor_wait(true); + WM_cursor_wait(true); - if (is_foo_format(name)) { - read_foo(name); - retval = BKE_READ_EXOTIC_OK_OTHER; - } - else + if (is_foo_format(name)) { + read_foo(name); + retval = BKE_READ_EXOTIC_OK_OTHER; + } + else #endif - { - retval = BKE_READ_EXOTIC_FAIL_FORMAT; - } + { + retval = BKE_READ_EXOTIC_FAIL_FORMAT; + } #if 0 - WM_cursor_wait(false); + WM_cursor_wait(false); #endif - } - } - } + } + } + } - return retval; + return retval; } void WM_file_autoexec_init(const char *filepath) { - if (G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) { - return; - } + if (G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) { + return; + } - if (G.f & G_FLAG_SCRIPT_AUTOEXEC) { - char path[FILE_MAX]; - BLI_split_dir_part(filepath, path, sizeof(path)); - if (BKE_autoexec_match(path)) { - G.f &= ~G_FLAG_SCRIPT_AUTOEXEC; - } - } + if (G.f & G_FLAG_SCRIPT_AUTOEXEC) { + char path[FILE_MAX]; + BLI_split_dir_part(filepath, path, sizeof(path)); + if (BKE_autoexec_match(path)) { + G.f &= ~G_FLAG_SCRIPT_AUTOEXEC; + } + } } void wm_file_read_report(bContext *C, Main *bmain) { - ReportList *reports = NULL; - Scene *sce; + ReportList *reports = NULL; + Scene *sce; - for (sce = bmain->scenes.first; sce; sce = sce->id.next) { - if (sce->r.engine[0] && - BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL) - { - if (reports == NULL) { - reports = CTX_wm_reports(C); - } + for (sce = bmain->scenes.first; sce; sce = sce->id.next) { + if (sce->r.engine[0] && + BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL) { + if (reports == NULL) { + reports = CTX_wm_reports(C); + } - BKE_reportf(reports, RPT_ERROR, - "Engine '%s' not available for scene '%s' (an add-on may need to be installed or enabled)", - sce->r.engine, sce->id.name + 2); - } - } + BKE_reportf(reports, + RPT_ERROR, + "Engine '%s' not available for scene '%s' (an add-on may need to be installed " + "or enabled)", + sce->r.engine, + sce->id.name + 2); + } + } - if (reports) { - if (!G.background) { - WM_report_banner_show(); - } - } + if (reports) { + if (!G.background) { + WM_report_banner_show(); + } + } } /** * Logic shared between #WM_file_read & #wm_homefile_read, * updates to make after reading a file. */ -static void wm_file_read_post( - bContext *C, const bool is_startup_file, const bool is_factory_startup, const bool reset_app_template) +static void wm_file_read_post(bContext *C, + const bool is_startup_file, + const bool is_factory_startup, + const bool reset_app_template) { - bool addons_loaded = false; - wmWindowManager *wm = CTX_wm_manager(C); + bool addons_loaded = false; + wmWindowManager *wm = CTX_wm_manager(C); - if (!G.background) { - /* remove windows which failed to be added via WM_check */ - wm_window_ghostwindows_remove_invalid(C, wm); - } + if (!G.background) { + /* remove windows which failed to be added via WM_check */ + wm_window_ghostwindows_remove_invalid(C, wm); + } - CTX_wm_window_set(C, wm->windows.first); + CTX_wm_window_set(C, wm->windows.first); #ifdef WITH_PYTHON - if (is_startup_file) { - /* possible python hasn't been initialized */ - if (CTX_py_init_get(C)) { - if (reset_app_template) { - /* Only run when we have a template path found. */ - if (BKE_appdir_app_template_any()) { - BPY_execute_string( - C, (const char *[]){"bl_app_template_utils", NULL}, - "bl_app_template_utils.reset()"); - } - /* sync addons, these may have changed from the defaults */ - BPY_execute_string( - C, (const char *[]){"addon_utils", NULL}, - "addon_utils.reset_all()"); - } - BPY_python_reset(C); - addons_loaded = true; - } - } - else { - /* run any texts that were loaded in and flagged as modules */ - BPY_python_reset(C); - addons_loaded = true; - } + if (is_startup_file) { + /* possible python hasn't been initialized */ + if (CTX_py_init_get(C)) { + if (reset_app_template) { + /* Only run when we have a template path found. */ + if (BKE_appdir_app_template_any()) { + BPY_execute_string( + C, (const char *[]){"bl_app_template_utils", NULL}, "bl_app_template_utils.reset()"); + } + /* sync addons, these may have changed from the defaults */ + BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()"); + } + BPY_python_reset(C); + addons_loaded = true; + } + } + else { + /* run any texts that were loaded in and flagged as modules */ + BPY_python_reset(C); + addons_loaded = true; + } #else - UNUSED_VARS(is_startup_file, reset_app_template); -#endif /* WITH_PYTHON */ + UNUSED_VARS(is_startup_file, reset_app_template); +#endif /* WITH_PYTHON */ - WM_operatortype_last_properties_clear_all(); + WM_operatortype_last_properties_clear_all(); - /* important to do before NULL'ing the context */ - Main *bmain = CTX_data_main(C); - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); - if (is_factory_startup) { - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST); - } + /* important to do before NULL'ing the context */ + Main *bmain = CTX_data_main(C); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); + if (is_factory_startup) { + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST); + } - /* After load post, so for example the driver namespace can be filled - * before evaluating the depsgraph. */ - DEG_on_visible_update(bmain, true); - wm_event_do_depsgraph(C); + /* After load post, so for example the driver namespace can be filled + * before evaluating the depsgraph. */ + DEG_on_visible_update(bmain, true); + wm_event_do_depsgraph(C); - ED_editors_init(C); + ED_editors_init(C); #if 1 - WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); + WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); #else - WM_msg_publish_static(CTX_wm_message_bus(C), WM_MSG_STATICTYPE_FILE_READ); + WM_msg_publish_static(CTX_wm_message_bus(C), WM_MSG_STATICTYPE_FILE_READ); #endif - /* report any errors. - * currently disabled if addons aren't yet loaded */ - if (addons_loaded) { - wm_file_read_report(C, bmain); - } - - if (!G.background) { - if (wm->undo_stack == NULL) { - wm->undo_stack = BKE_undosys_stack_create(); - } - else { - BKE_undosys_stack_clear(wm->undo_stack); - } - BKE_undosys_stack_init_from_main(wm->undo_stack, bmain); - BKE_undosys_stack_init_from_context(wm->undo_stack, C); - } - - if (!G.background) { - /* in background mode this makes it hard to load - * a blend file and do anything since the screen - * won't be set to a valid value again */ - CTX_wm_window_set(C, NULL); /* exits queues */ - - /* Ensure tools are registered. */ - WM_toolsystem_init(C); - } + /* report any errors. + * currently disabled if addons aren't yet loaded */ + if (addons_loaded) { + wm_file_read_report(C, bmain); + } + + if (!G.background) { + if (wm->undo_stack == NULL) { + wm->undo_stack = BKE_undosys_stack_create(); + } + else { + BKE_undosys_stack_clear(wm->undo_stack); + } + BKE_undosys_stack_init_from_main(wm->undo_stack, bmain); + BKE_undosys_stack_init_from_context(wm->undo_stack, C); + } + + if (!G.background) { + /* in background mode this makes it hard to load + * a blend file and do anything since the screen + * won't be set to a valid value again */ + CTX_wm_window_set(C, NULL); /* exits queues */ + + /* Ensure tools are registered. */ + WM_toolsystem_init(C); + } } bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) { - /* assume automated tasks with background, don't write recent file list */ - const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0); - bool success = false; - int retval; - - /* so we can get the error message */ - errno = 0; - - WM_cursor_wait(1); - - BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); - - UI_view2d_zoom_cache_reset(); - - /* first try to append data from exotic file formats... */ - /* it throws error box when file doesn't exist and returns -1 */ - /* note; it should set some error message somewhere... (ton) */ - retval = wm_read_exotic(filepath); - - /* we didn't succeed, now try to read Blender file */ - if (retval == BKE_READ_EXOTIC_OK_BLEND) { - const int G_f_orig = G.f; - ListBase wmbase; - - /* put aside screens to match with persistent windows later */ - /* also exit screens and editors */ - wm_window_match_init(C, &wmbase); - - /* confusing this global... */ - G.relbase_valid = 1; - retval = BKE_blendfile_read( - C, filepath, - &(const struct BlendFileReadParams){0}, - reports); - - /* BKE_file_read sets new Main into context. */ - Main *bmain = CTX_data_main(C); - - /* when loading startup.blend's, we can be left with a blank path */ - if (BKE_main_blendfile_path(bmain)[0] != '\0') { - G.save_over = 1; - } - else { - G.save_over = 0; - G.relbase_valid = 0; - } - - /* this flag is initialized by the operator but overwritten on read. - * need to re-enable it here else drivers + registered scripts wont work. */ - if (G.f != G_f_orig) { - const int flags_keep = G_FLAG_ALL_RUNTIME; - G.f &= G_FLAG_ALL_READFILE; - G.f = (G.f & ~flags_keep) | (G_f_orig & flags_keep); - } - - /* match the read WM with current WM */ - wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm); - WM_check(C); /* opens window(s), checks keymaps */ - - if (retval == BKE_BLENDFILE_READ_OK_USERPREFS) { - /* in case a userdef is read from regular .blend */ - wm_init_userdef(bmain, false); - } - - if (retval != BKE_BLENDFILE_READ_FAIL) { - if (do_history) { - wm_history_file_update(); - } - } - - wm_file_read_post(C, false, false, false); - - success = true; - } + /* assume automated tasks with background, don't write recent file list */ + const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0); + bool success = false; + int retval; + + /* so we can get the error message */ + errno = 0; + + WM_cursor_wait(1); + + BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); + + UI_view2d_zoom_cache_reset(); + + /* first try to append data from exotic file formats... */ + /* it throws error box when file doesn't exist and returns -1 */ + /* note; it should set some error message somewhere... (ton) */ + retval = wm_read_exotic(filepath); + + /* we didn't succeed, now try to read Blender file */ + if (retval == BKE_READ_EXOTIC_OK_BLEND) { + const int G_f_orig = G.f; + ListBase wmbase; + + /* put aside screens to match with persistent windows later */ + /* also exit screens and editors */ + wm_window_match_init(C, &wmbase); + + /* confusing this global... */ + G.relbase_valid = 1; + retval = BKE_blendfile_read(C, filepath, &(const struct BlendFileReadParams){0}, reports); + + /* BKE_file_read sets new Main into context. */ + Main *bmain = CTX_data_main(C); + + /* when loading startup.blend's, we can be left with a blank path */ + if (BKE_main_blendfile_path(bmain)[0] != '\0') { + G.save_over = 1; + } + else { + G.save_over = 0; + G.relbase_valid = 0; + } + + /* this flag is initialized by the operator but overwritten on read. + * need to re-enable it here else drivers + registered scripts wont work. */ + if (G.f != G_f_orig) { + const int flags_keep = G_FLAG_ALL_RUNTIME; + G.f &= G_FLAG_ALL_READFILE; + G.f = (G.f & ~flags_keep) | (G_f_orig & flags_keep); + } + + /* match the read WM with current WM */ + wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm); + WM_check(C); /* opens window(s), checks keymaps */ + + if (retval == BKE_BLENDFILE_READ_OK_USERPREFS) { + /* in case a userdef is read from regular .blend */ + wm_init_userdef(bmain, false); + } + + if (retval != BKE_BLENDFILE_READ_FAIL) { + if (do_history) { + wm_history_file_update(); + } + } + + wm_file_read_post(C, false, false, false); + + success = true; + } #if 0 - else if (retval == BKE_READ_EXOTIC_OK_OTHER) - BKE_undo_write(C, "Import file"); + else if (retval == BKE_READ_EXOTIC_OK_OTHER) + BKE_undo_write(C, "Import file"); #endif - else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) { - BKE_reportf(reports, RPT_ERROR, "Cannot read file '%s': %s", filepath, - errno ? strerror(errno) : TIP_("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'", filepath); - } - else if (retval == BKE_READ_EXOTIC_FAIL_PATH) { - BKE_reportf(reports, RPT_ERROR, "File path '%s' invalid", filepath); - } - else { - BKE_reportf(reports, RPT_ERROR, "Unknown error loading '%s'", filepath); - BLI_assert(!"invalid 'retval'"); - } - - - if (success == false) { - /* remove from recent files list */ - if (do_history) { - RecentFile *recent = wm_file_history_find(filepath); - if (recent) { - wm_history_file_free(recent); - wm_history_file_write(); - } - } - } - - WM_cursor_wait(0); - - return success; - + else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) { + BKE_reportf(reports, + RPT_ERROR, + "Cannot read file '%s': %s", + filepath, + errno ? strerror(errno) : TIP_("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'", filepath); + } + else if (retval == BKE_READ_EXOTIC_FAIL_PATH) { + BKE_reportf(reports, RPT_ERROR, "File path '%s' invalid", filepath); + } + else { + BKE_reportf(reports, RPT_ERROR, "Unknown error loading '%s'", filepath); + BLI_assert(!"invalid 'retval'"); + } + + if (success == false) { + /* remove from recent files list */ + if (do_history) { + RecentFile *recent = wm_file_history_find(filepath); + if (recent) { + wm_history_file_free(recent); + wm_history_file_write(); + } + } + } + + WM_cursor_wait(0); + + return success; } static struct { - char app_template[64]; - bool override; + char app_template[64]; + bool override; } wm_init_state_app_template = {{0}}; /** @@ -698,38 +698,39 @@ static struct { */ void WM_init_state_app_template_set(const char *app_template) { - if (app_template) { - STRNCPY(wm_init_state_app_template.app_template, app_template); - wm_init_state_app_template.override = true; - } - else { - wm_init_state_app_template.app_template[0] = '\0'; - wm_init_state_app_template.override = false; - } + if (app_template) { + STRNCPY(wm_init_state_app_template.app_template, app_template); + wm_init_state_app_template.override = true; + } + else { + wm_init_state_app_template.app_template[0] = '\0'; + wm_init_state_app_template.override = false; + } } const char *WM_init_state_app_template_get(void) { - return wm_init_state_app_template.override ? wm_init_state_app_template.app_template : NULL; + return wm_init_state_app_template.override ? wm_init_state_app_template.app_template : NULL; } - static bool wm_app_template_has_userpref(const char *app_template) { - /* Test if app template provides a userpref.blend. If not, we will - * share user preferences with the rest of Blender. */ - if (!app_template && app_template[0]) { - return false; - } + /* Test if app template provides a userpref.blend. If not, we will + * share user preferences with the rest of Blender. */ + if (!app_template && app_template[0]) { + return false; + } - char app_template_path[FILE_MAX]; - if (!BKE_appdir_app_template_id_search(app_template, app_template_path, sizeof(app_template_path))) { - return false; - } + char app_template_path[FILE_MAX]; + if (!BKE_appdir_app_template_id_search( + app_template, app_template_path, sizeof(app_template_path))) { + return false; + } - char userpref_path[FILE_MAX]; - BLI_path_join(userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE, NULL); - return BLI_exists(userpref_path); + char userpref_path[FILE_MAX]; + BLI_path_join( + userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE, NULL); + return BLI_exists(userpref_path); } /** @@ -744,280 +745,296 @@ static bool wm_app_template_has_userpref(const char *app_template) * \param app_template_override: Template to use instead of the template defined in user-preferences. * When not-null, this is written into the user preferences. */ -void wm_homefile_read( - bContext *C, ReportList *reports, - bool use_factory_settings, bool use_empty_data, bool use_userdef, - const char *filepath_startup_override, const char *app_template_override, - bool *r_is_factory_startup) -{ - Main *bmain = G_MAIN; /* Context does not always have valid main pointer here... */ - ListBase wmbase; - bool success = false; - - bool filepath_startup_is_factory = true; - char filepath_startup[FILE_MAX]; - char filepath_userdef[FILE_MAX]; - - /* When 'app_template' is set: '{BLENDER_USER_CONFIG}/{app_template}' */ - char app_template_system[FILE_MAX]; - /* When 'app_template' is set: '{BLENDER_SYSTEM_SCRIPTS}/startup/bl_app_templates_system/{app_template}' */ - char app_template_config[FILE_MAX]; - - /* Indicates whether user preferences were really load from memory. - * - * This is used for versioning code, and for this we can not rely on use_factory_settings - * passed via argument. This is because there might be configuration folder - * exists but it might not have userpref.blend and in this case we fallback to - * reading home file from memory. - * - * And in this case versioning code is to be run. - */ - bool read_userdef_from_memory = false; - eBLOReadSkip skip_flags = use_userdef ? 0 : BLO_READ_SKIP_USERDEF; - - /* True if we load startup.blend from memory or use app-template startup.blend which the user hasn't saved. */ - bool is_factory_startup = true; - - /* options exclude eachother */ - BLI_assert((use_factory_settings && filepath_startup_override) == 0); - - if ((G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) == 0) { - SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC); - } - - BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); - - UI_view2d_zoom_cache_reset(); - - G.relbase_valid = 0; - - /* put aside screens to match with persistent windows later */ - wm_window_match_init(C, &wmbase); - - filepath_startup[0] = '\0'; - filepath_userdef[0] = '\0'; - app_template_system[0] = '\0'; - app_template_config[0] = '\0'; - - const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); - if (!use_factory_settings) { - if (cfgdir) { - BLI_path_join(filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL); - filepath_startup_is_factory = false; - if (use_userdef) { - BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL); - } - } - else { - use_factory_settings = true; - } - - if (filepath_startup_override) { - BLI_strncpy(filepath_startup, filepath_startup_override, FILE_MAX); - filepath_startup_is_factory = false; - } - } - - /* load preferences before startup.blend */ - if (use_userdef) { - if (!use_factory_settings && BLI_exists(filepath_userdef)) { - UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL); - if (userdef != NULL) { - BKE_blender_userdef_data_set_and_free(userdef); - userdef = NULL; - - skip_flags |= BLO_READ_SKIP_USERDEF; - printf("Read prefs: %s\n", filepath_userdef); - } - } - } - - const char *app_template = NULL; - bool update_defaults = false; - bool reset_app_template = false; - - if (filepath_startup_override != NULL) { - /* pass */ - } - else if (app_template_override) { - /* This may be clearing the current template by setting to an empty string. */ - app_template = app_template_override; - } - else if (!use_factory_settings && U.app_template[0]) { - app_template = U.app_template; - } - - if ((!app_template && U.app_template[0]) || - (app_template && !STREQ(app_template, U.app_template))) - { - /* Always load UI when switching to another template. */ - G.fileflags &= ~G_FILE_NO_UI; - reset_app_template = true; - } - - if ((app_template != NULL) && (app_template[0] != '\0')) { - if (!BKE_appdir_app_template_id_search( - app_template, app_template_system, sizeof(app_template_system))) - { - /* Can safely continue with code below, just warn it's not found. */ - BKE_reportf(reports, RPT_WARNING, "Application Template '%s' not found", app_template); - } - - /* Insert template name into startup file. */ - - /* note that the path is being set even when 'use_factory_settings == true' - * this is done so we can load a templates factory-settings */ - if (!use_factory_settings) { - BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL); - BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_config, BLENDER_STARTUP_FILE, NULL); - filepath_startup_is_factory = false; - if (BLI_access(filepath_startup, R_OK) != 0) { - filepath_startup[0] = '\0'; - } - } - else { - filepath_startup[0] = '\0'; - } - - if (filepath_startup[0] == '\0') { - BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_system, BLENDER_STARTUP_FILE, NULL); - filepath_startup_is_factory = true; - - /* Update defaults only for system templates. */ - update_defaults = true; - } - } - - if (!use_factory_settings || (filepath_startup[0] != '\0')) { - if (BLI_access(filepath_startup, R_OK) == 0) { - success = BKE_blendfile_read( - C, filepath_startup, - &(const struct BlendFileReadParams){ - .is_startup = true, - .skip_flags = skip_flags, - }, - NULL) != BKE_BLENDFILE_READ_FAIL; - } - if (BLI_listbase_is_empty(&U.themes)) { - if (G.debug & G_DEBUG) { - printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", filepath_startup); - } - success = false; - } - if (success) { - if (update_defaults) { - BLO_update_defaults_startup_blend(CTX_data_main(C), app_template); - } - is_factory_startup = filepath_startup_is_factory; - } - } - - if (success == false && filepath_startup_override && reports) { - /* We can not return from here because wm is already reset */ - BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", filepath_startup_override); - } - - if (success == false) { - success = BKE_blendfile_read_from_memory( - C, datatoc_startup_blend, datatoc_startup_blend_size, true, - &(const struct BlendFileReadParams){ - .is_startup = true, - .skip_flags = skip_flags, - }, - NULL); - if (success) { - if (use_userdef) { - if ((skip_flags & BLO_READ_SKIP_USERDEF) == 0) { - read_userdef_from_memory = true; - } - } - } - if (BLI_listbase_is_empty(&wmbase)) { - wm_clear_default_size(C); - } - } - - if (use_empty_data) { - BKE_blendfile_read_make_empty(C); - } - - /* Load template preferences, - * unlike regular preferences we only use some of the settings, - * see: BKE_blender_userdef_set_app_template */ - if (app_template_system[0] != '\0') { - char temp_path[FILE_MAX]; - temp_path[0] = '\0'; - if (!use_factory_settings) { - BLI_path_join(temp_path, sizeof(temp_path), app_template_config, BLENDER_USERPREF_FILE, NULL); - if (BLI_access(temp_path, R_OK) != 0) { - temp_path[0] = '\0'; - } - } - - if (temp_path[0] == '\0') { - BLI_path_join(temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL); - } - - if (use_userdef) { - UserDef *userdef_template = NULL; - /* just avoids missing file warning */ - if (BLI_exists(temp_path)) { - userdef_template = BKE_blendfile_userdef_read(temp_path, NULL); - } - if (userdef_template == NULL) { - /* we need to have preferences load to overwrite preferences from previous template */ - userdef_template = BKE_blendfile_userdef_read_from_memory( - datatoc_startup_blend, datatoc_startup_blend_size, NULL); - read_userdef_from_memory = true; - } - if (userdef_template) { - BKE_blender_userdef_app_template_data_set_and_free(userdef_template); - userdef_template = NULL; - } - } - } - - if (app_template_override) { - BLI_strncpy(U.app_template, app_template_override, sizeof(U.app_template)); - } - - /* 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; - - bmain = CTX_data_main(C); - - if (use_userdef) { - /* check userdef before open window, keymaps etc */ - wm_init_userdef(bmain, read_userdef_from_memory); - reset_app_template = true; - } - - /* match the read WM with current WM */ - wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm); - - if (use_factory_settings) { - /* Clear keymaps because the current default keymap may have been initialized from user preferences, - * which have been reset. */ - for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { - if (wm->defaultconf) { - wm->defaultconf->flag &= ~KEYCONF_INIT_DEFAULT; - } - } - } - - WM_check(C); /* opens window(s), checks keymaps */ - - bmain->name[0] = '\0'; - - /* start with save preference untitled.blend */ - G.save_over = 0; - - wm_file_read_post(C, true, is_factory_startup, reset_app_template); - - if (r_is_factory_startup) { - *r_is_factory_startup = is_factory_startup; - } +void wm_homefile_read(bContext *C, + ReportList *reports, + bool use_factory_settings, + bool use_empty_data, + bool use_userdef, + const char *filepath_startup_override, + const char *app_template_override, + bool *r_is_factory_startup) +{ + Main *bmain = G_MAIN; /* Context does not always have valid main pointer here... */ + ListBase wmbase; + bool success = false; + + bool filepath_startup_is_factory = true; + char filepath_startup[FILE_MAX]; + char filepath_userdef[FILE_MAX]; + + /* When 'app_template' is set: '{BLENDER_USER_CONFIG}/{app_template}' */ + char app_template_system[FILE_MAX]; + /* When 'app_template' is set: '{BLENDER_SYSTEM_SCRIPTS}/startup/bl_app_templates_system/{app_template}' */ + char app_template_config[FILE_MAX]; + + /* Indicates whether user preferences were really load from memory. + * + * This is used for versioning code, and for this we can not rely on use_factory_settings + * passed via argument. This is because there might be configuration folder + * exists but it might not have userpref.blend and in this case we fallback to + * reading home file from memory. + * + * And in this case versioning code is to be run. + */ + bool read_userdef_from_memory = false; + eBLOReadSkip skip_flags = use_userdef ? 0 : BLO_READ_SKIP_USERDEF; + + /* True if we load startup.blend from memory or use app-template startup.blend which the user hasn't saved. */ + bool is_factory_startup = true; + + /* options exclude eachother */ + BLI_assert((use_factory_settings && filepath_startup_override) == 0); + + if ((G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) == 0) { + SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC); + } + + BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); + + UI_view2d_zoom_cache_reset(); + + G.relbase_valid = 0; + + /* put aside screens to match with persistent windows later */ + wm_window_match_init(C, &wmbase); + + filepath_startup[0] = '\0'; + filepath_userdef[0] = '\0'; + app_template_system[0] = '\0'; + app_template_config[0] = '\0'; + + const char *const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); + if (!use_factory_settings) { + if (cfgdir) { + BLI_path_join( + filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL); + filepath_startup_is_factory = false; + if (use_userdef) { + BLI_path_join( + filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL); + } + } + else { + use_factory_settings = true; + } + + if (filepath_startup_override) { + BLI_strncpy(filepath_startup, filepath_startup_override, FILE_MAX); + filepath_startup_is_factory = false; + } + } + + /* load preferences before startup.blend */ + if (use_userdef) { + if (!use_factory_settings && BLI_exists(filepath_userdef)) { + UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL); + if (userdef != NULL) { + BKE_blender_userdef_data_set_and_free(userdef); + userdef = NULL; + + skip_flags |= BLO_READ_SKIP_USERDEF; + printf("Read prefs: %s\n", filepath_userdef); + } + } + } + + const char *app_template = NULL; + bool update_defaults = false; + bool reset_app_template = false; + + if (filepath_startup_override != NULL) { + /* pass */ + } + else if (app_template_override) { + /* This may be clearing the current template by setting to an empty string. */ + app_template = app_template_override; + } + else if (!use_factory_settings && U.app_template[0]) { + app_template = U.app_template; + } + + if ((!app_template && U.app_template[0]) || + (app_template && !STREQ(app_template, U.app_template))) { + /* Always load UI when switching to another template. */ + G.fileflags &= ~G_FILE_NO_UI; + reset_app_template = true; + } + + if ((app_template != NULL) && (app_template[0] != '\0')) { + if (!BKE_appdir_app_template_id_search( + app_template, app_template_system, sizeof(app_template_system))) { + /* Can safely continue with code below, just warn it's not found. */ + BKE_reportf(reports, RPT_WARNING, "Application Template '%s' not found", app_template); + } + + /* Insert template name into startup file. */ + + /* note that the path is being set even when 'use_factory_settings == true' + * this is done so we can load a templates factory-settings */ + if (!use_factory_settings) { + BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL); + BLI_path_join(filepath_startup, + sizeof(filepath_startup), + app_template_config, + BLENDER_STARTUP_FILE, + NULL); + filepath_startup_is_factory = false; + if (BLI_access(filepath_startup, R_OK) != 0) { + filepath_startup[0] = '\0'; + } + } + else { + filepath_startup[0] = '\0'; + } + + if (filepath_startup[0] == '\0') { + BLI_path_join(filepath_startup, + sizeof(filepath_startup), + app_template_system, + BLENDER_STARTUP_FILE, + NULL); + filepath_startup_is_factory = true; + + /* Update defaults only for system templates. */ + update_defaults = true; + } + } + + if (!use_factory_settings || (filepath_startup[0] != '\0')) { + if (BLI_access(filepath_startup, R_OK) == 0) { + success = BKE_blendfile_read(C, + filepath_startup, + &(const struct BlendFileReadParams){ + .is_startup = true, + .skip_flags = skip_flags, + }, + NULL) != BKE_BLENDFILE_READ_FAIL; + } + if (BLI_listbase_is_empty(&U.themes)) { + if (G.debug & G_DEBUG) { + printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", + filepath_startup); + } + success = false; + } + if (success) { + if (update_defaults) { + BLO_update_defaults_startup_blend(CTX_data_main(C), app_template); + } + is_factory_startup = filepath_startup_is_factory; + } + } + + if (success == false && filepath_startup_override && reports) { + /* We can not return from here because wm is already reset */ + BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", filepath_startup_override); + } + + if (success == false) { + success = BKE_blendfile_read_from_memory(C, + datatoc_startup_blend, + datatoc_startup_blend_size, + true, + &(const struct BlendFileReadParams){ + .is_startup = true, + .skip_flags = skip_flags, + }, + NULL); + if (success) { + if (use_userdef) { + if ((skip_flags & BLO_READ_SKIP_USERDEF) == 0) { + read_userdef_from_memory = true; + } + } + } + if (BLI_listbase_is_empty(&wmbase)) { + wm_clear_default_size(C); + } + } + + if (use_empty_data) { + BKE_blendfile_read_make_empty(C); + } + + /* Load template preferences, + * unlike regular preferences we only use some of the settings, + * see: BKE_blender_userdef_set_app_template */ + if (app_template_system[0] != '\0') { + char temp_path[FILE_MAX]; + temp_path[0] = '\0'; + if (!use_factory_settings) { + BLI_path_join( + temp_path, sizeof(temp_path), app_template_config, BLENDER_USERPREF_FILE, NULL); + if (BLI_access(temp_path, R_OK) != 0) { + temp_path[0] = '\0'; + } + } + + if (temp_path[0] == '\0') { + BLI_path_join( + temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL); + } + + if (use_userdef) { + UserDef *userdef_template = NULL; + /* just avoids missing file warning */ + if (BLI_exists(temp_path)) { + userdef_template = BKE_blendfile_userdef_read(temp_path, NULL); + } + if (userdef_template == NULL) { + /* we need to have preferences load to overwrite preferences from previous template */ + userdef_template = BKE_blendfile_userdef_read_from_memory( + datatoc_startup_blend, datatoc_startup_blend_size, NULL); + read_userdef_from_memory = true; + } + if (userdef_template) { + BKE_blender_userdef_app_template_data_set_and_free(userdef_template); + userdef_template = NULL; + } + } + } + + if (app_template_override) { + BLI_strncpy(U.app_template, app_template_override, sizeof(U.app_template)); + } + + /* 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; + + bmain = CTX_data_main(C); + + if (use_userdef) { + /* check userdef before open window, keymaps etc */ + wm_init_userdef(bmain, read_userdef_from_memory); + reset_app_template = true; + } + + /* match the read WM with current WM */ + wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm); + + if (use_factory_settings) { + /* Clear keymaps because the current default keymap may have been initialized from user preferences, + * which have been reset. */ + for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + if (wm->defaultconf) { + wm->defaultconf->flag &= ~KEYCONF_INIT_DEFAULT; + } + } + } + + WM_check(C); /* opens window(s), checks keymaps */ + + bmain->name[0] = '\0'; + + /* start with save preference untitled.blend */ + G.save_over = 0; + + wm_file_read_post(C, true, is_factory_startup, reset_app_template); + + if (r_is_factory_startup) { + *r_is_factory_startup = is_factory_startup; + } } /** \name WM History File API @@ -1025,55 +1042,55 @@ void wm_homefile_read( void wm_history_file_read(void) { - char name[FILE_MAX]; - LinkNode *l, *lines; - struct RecentFile *recent; - const char *line; - int num; - const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); + char name[FILE_MAX]; + LinkNode *l, *lines; + struct RecentFile *recent; + const char *line; + int num; + const char *const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); - if (!cfgdir) { - return; - } + if (!cfgdir) { + return; + } - BLI_make_file_string("/", name, cfgdir, BLENDER_HISTORY_FILE); + BLI_make_file_string("/", name, cfgdir, BLENDER_HISTORY_FILE); - lines = BLI_file_read_as_lines(name); + lines = BLI_file_read_as_lines(name); - BLI_listbase_clear(&G.recent_files); + BLI_listbase_clear(&G.recent_files); - /* read list of recent opened files from recent-files.txt to memory */ - for (l = lines, num = 0; l && (num < U.recent_files); l = l->next) { - line = l->link; - /* don't check if files exist, causes slow startup for remote/external drives */ - if (line[0]) { - recent = (RecentFile *)MEM_mallocN(sizeof(RecentFile), "RecentFile"); - BLI_addtail(&(G.recent_files), recent); - recent->filepath = BLI_strdup(line); - num++; - } - } + /* read list of recent opened files from recent-files.txt to memory */ + for (l = lines, num = 0; l && (num < U.recent_files); l = l->next) { + line = l->link; + /* don't check if files exist, causes slow startup for remote/external drives */ + if (line[0]) { + recent = (RecentFile *)MEM_mallocN(sizeof(RecentFile), "RecentFile"); + BLI_addtail(&(G.recent_files), recent); + recent->filepath = BLI_strdup(line); + num++; + } + } - BLI_file_free_lines(lines); + BLI_file_free_lines(lines); } static RecentFile *wm_history_file_new(const char *filepath) { - RecentFile *recent = MEM_mallocN(sizeof(RecentFile), "RecentFile"); - recent->filepath = BLI_strdup(filepath); - return recent; + RecentFile *recent = MEM_mallocN(sizeof(RecentFile), "RecentFile"); + recent->filepath = BLI_strdup(filepath); + return recent; } static void wm_history_file_free(RecentFile *recent) { - BLI_assert(BLI_findindex(&G.recent_files, recent) != -1); - MEM_freeN(recent->filepath); - BLI_freelinkN(&G.recent_files, recent); + BLI_assert(BLI_findindex(&G.recent_files, recent) != -1); + MEM_freeN(recent->filepath); + BLI_freelinkN(&G.recent_files, recent); } static RecentFile *wm_file_history_find(const char *filepath) { - return BLI_findstring_ptr(&G.recent_files, filepath, offsetof(RecentFile, filepath)); + return BLI_findstring_ptr(&G.recent_files, filepath, offsetof(RecentFile, filepath)); } /** @@ -1082,26 +1099,26 @@ static RecentFile *wm_file_history_find(const char *filepath) */ static void wm_history_file_write(void) { - const char *user_config_dir; - char name[FILE_MAX]; - FILE *fp; + const char *user_config_dir; + char name[FILE_MAX]; + FILE *fp; - /* will be NULL in background mode */ - user_config_dir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL); - if (!user_config_dir) { - return; - } + /* will be NULL in background mode */ + user_config_dir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL); + if (!user_config_dir) { + return; + } - BLI_make_file_string("/", name, user_config_dir, BLENDER_HISTORY_FILE); + BLI_make_file_string("/", name, user_config_dir, BLENDER_HISTORY_FILE); - fp = BLI_fopen(name, "w"); - if (fp) { - struct RecentFile *recent; - for (recent = G.recent_files.first; recent; recent = recent->next) { - fprintf(fp, "%s\n", recent->filepath); - } - fclose(fp); - } + fp = BLI_fopen(name, "w"); + if (fp) { + struct RecentFile *recent; + for (recent = G.recent_files.first; recent; recent = recent->next) { + fprintf(fp, "%s\n", recent->filepath); + } + fclose(fp); + } } /** @@ -1109,138 +1126,158 @@ static void wm_history_file_write(void) */ static void wm_history_file_update(void) { - RecentFile *recent; - const char *blendfile_name = BKE_main_blendfile_path_from_global(); + RecentFile *recent; + const char *blendfile_name = BKE_main_blendfile_path_from_global(); - /* no write history for recovered startup files */ - if (blendfile_name[0] == '\0') { - return; - } + /* no write history for recovered startup files */ + if (blendfile_name[0] == '\0') { + return; + } - recent = G.recent_files.first; - /* refresh recent-files.txt of recent opened files, when current file was changed */ - if (!(recent) || (BLI_path_cmp(recent->filepath, blendfile_name) != 0)) { + recent = G.recent_files.first; + /* refresh recent-files.txt of recent opened files, when current file was changed */ + if (!(recent) || (BLI_path_cmp(recent->filepath, blendfile_name) != 0)) { - recent = wm_file_history_find(blendfile_name); - if (recent) { - BLI_remlink(&G.recent_files, recent); - } - else { - RecentFile *recent_next; - for (recent = BLI_findlink(&G.recent_files, U.recent_files - 1); recent; recent = recent_next) { - recent_next = recent->next; - wm_history_file_free(recent); - } - recent = wm_history_file_new(blendfile_name); - } + recent = wm_file_history_find(blendfile_name); + if (recent) { + BLI_remlink(&G.recent_files, recent); + } + else { + RecentFile *recent_next; + for (recent = BLI_findlink(&G.recent_files, U.recent_files - 1); recent; + recent = recent_next) { + recent_next = recent->next; + wm_history_file_free(recent); + } + recent = wm_history_file_new(blendfile_name); + } - /* add current file to the beginning of list */ - BLI_addhead(&(G.recent_files), recent); + /* add current file to the beginning of list */ + BLI_addhead(&(G.recent_files), recent); - /* write current file to recent-files.txt */ - wm_history_file_write(); + /* write current file to recent-files.txt */ + wm_history_file_write(); - /* also update most recent files on System */ - GHOST_addToSystemRecentFiles(blendfile_name); - } + /* also update most recent files on System */ + GHOST_addToSystemRecentFiles(blendfile_name); + } } /** \} */ - /* screen can be NULL */ -static ImBuf *blend_file_thumb(const bContext *C, Scene *scene, bScreen *screen, BlendThumbnail **thumb_pt) -{ - /* will be scaled down, but gives some nice oversampling */ - ImBuf *ibuf; - BlendThumbnail *thumb; - char err_out[256] = "unknown"; - - /* screen if no camera found */ - ScrArea *sa = NULL; - ARegion *ar = NULL; - View3D *v3d = NULL; - - /* In case we are given a valid thumbnail data, just generate image from it. */ - if (*thumb_pt) { - thumb = *thumb_pt; - return BKE_main_thumbnail_to_imbuf(NULL, thumb); - } - - /* scene can be NULL if running a script at startup and calling the save operator */ - if (G.background || scene == NULL) { - return NULL; - } - - if ((scene->camera == NULL) && (screen != NULL)) { - sa = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0); - ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar) { - v3d = sa->spacedata.first; - } - } - - if (scene->camera == NULL && v3d == NULL) { - return NULL; - } - - /* gets scaled to BLEN_THUMB_SIZE */ - Depsgraph *depsgraph = CTX_data_depsgraph(C); - - if (scene->camera) { - ibuf = ED_view3d_draw_offscreen_imbuf_simple( - depsgraph, scene, OB_SOLID, scene->camera, - BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL, - NULL, err_out); - } - else { - ibuf = ED_view3d_draw_offscreen_imbuf( - depsgraph, scene, OB_SOLID, v3d, ar, - BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL, - NULL, err_out); - } - - if (ibuf) { - float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); - - /* dirty oversampling */ - IMB_scaleImBuf(ibuf, BLEN_THUMB_SIZE, BLEN_THUMB_SIZE); - - /* add pretty overlay */ - IMB_thumb_overlay_blend(ibuf->rect, ibuf->x, ibuf->y, aspect); - - thumb = BKE_main_thumbnail_from_imbuf(NULL, ibuf); - } - else { - /* '*thumb_pt' needs to stay NULL to prevent a bad thumbnail from being handled */ - fprintf(stderr, "blend_file_thumb failed to create thumbnail: %s\n", err_out); - thumb = NULL; - } - - /* must be freed by caller */ - *thumb_pt = thumb; - - return ibuf; +static ImBuf *blend_file_thumb(const bContext *C, + Scene *scene, + bScreen *screen, + BlendThumbnail **thumb_pt) +{ + /* will be scaled down, but gives some nice oversampling */ + ImBuf *ibuf; + BlendThumbnail *thumb; + char err_out[256] = "unknown"; + + /* screen if no camera found */ + ScrArea *sa = NULL; + ARegion *ar = NULL; + View3D *v3d = NULL; + + /* In case we are given a valid thumbnail data, just generate image from it. */ + if (*thumb_pt) { + thumb = *thumb_pt; + return BKE_main_thumbnail_to_imbuf(NULL, thumb); + } + + /* scene can be NULL if running a script at startup and calling the save operator */ + if (G.background || scene == NULL) { + return NULL; + } + + if ((scene->camera == NULL) && (screen != NULL)) { + sa = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0); + ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar) { + v3d = sa->spacedata.first; + } + } + + if (scene->camera == NULL && v3d == NULL) { + return NULL; + } + + /* gets scaled to BLEN_THUMB_SIZE */ + Depsgraph *depsgraph = CTX_data_depsgraph(C); + + if (scene->camera) { + ibuf = ED_view3d_draw_offscreen_imbuf_simple(depsgraph, + scene, + OB_SOLID, + scene->camera, + BLEN_THUMB_SIZE * 2, + BLEN_THUMB_SIZE * 2, + IB_rect, + V3D_OFSDRAW_NONE, + R_ALPHAPREMUL, + 0, + NULL, + NULL, + err_out); + } + else { + ibuf = ED_view3d_draw_offscreen_imbuf(depsgraph, + scene, + OB_SOLID, + v3d, + ar, + BLEN_THUMB_SIZE * 2, + BLEN_THUMB_SIZE * 2, + IB_rect, + V3D_OFSDRAW_NONE, + R_ALPHAPREMUL, + 0, + NULL, + NULL, + err_out); + } + + if (ibuf) { + float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); + + /* dirty oversampling */ + IMB_scaleImBuf(ibuf, BLEN_THUMB_SIZE, BLEN_THUMB_SIZE); + + /* add pretty overlay */ + IMB_thumb_overlay_blend(ibuf->rect, ibuf->x, ibuf->y, aspect); + + thumb = BKE_main_thumbnail_from_imbuf(NULL, ibuf); + } + else { + /* '*thumb_pt' needs to stay NULL to prevent a bad thumbnail from being handled */ + fprintf(stderr, "blend_file_thumb failed to create thumbnail: %s\n", err_out); + thumb = NULL; + } + + /* must be freed by caller */ + *thumb_pt = thumb; + + return ibuf; } /* easy access from gdb */ bool write_crash_blend(void) { - char path[FILE_MAX]; - int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on crash file */ + char path[FILE_MAX]; + int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on crash file */ - BLI_strncpy(path, BKE_main_blendfile_path_from_global(), sizeof(path)); - BLI_path_extension_replace(path, sizeof(path), "_crash.blend"); - if (BLO_write_file(G_MAIN, path, fileflags, NULL, NULL)) { - printf("written: %s\n", path); - return 1; - } - else { - printf("failed: %s\n", path); - return 0; - } + BLI_strncpy(path, BKE_main_blendfile_path_from_global(), sizeof(path)); + BLI_path_extension_replace(path, sizeof(path), "_crash.blend"); + if (BLO_write_file(G_MAIN, path, fileflags, NULL, NULL)) { + printf("written: %s\n", path); + return 1; + } + else { + printf("failed: %s\n", path); + return 0; + } } /** @@ -1248,246 +1285,245 @@ bool write_crash_blend(void) */ static bool wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *reports) { - Main *bmain = CTX_data_main(C); - Library *li; - int len; - int ok = false; - BlendThumbnail *thumb, *main_thumb; - ImBuf *ibuf_thumb = NULL; - - len = strlen(filepath); + Main *bmain = CTX_data_main(C); + Library *li; + int len; + int ok = false; + BlendThumbnail *thumb, *main_thumb; + ImBuf *ibuf_thumb = NULL; + + len = strlen(filepath); - if (len == 0) { - BKE_report(reports, RPT_ERROR, "Path is empty, cannot save"); - return ok; - } + if (len == 0) { + BKE_report(reports, RPT_ERROR, "Path is empty, cannot save"); + return ok; + } - if (len >= FILE_MAX) { - BKE_report(reports, RPT_ERROR, "Path too long, cannot save"); - return ok; - } + if (len >= FILE_MAX) { + BKE_report(reports, RPT_ERROR, "Path too long, cannot save"); + return ok; + } - /* Check if file write permission is ok */ - if (BLI_exists(filepath) && !BLI_file_is_writable(filepath)) { - BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath); - return ok; - } + /* Check if file write permission is ok */ + if (BLI_exists(filepath) && !BLI_file_is_writable(filepath)) { + BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath); + return ok; + } - /* note: used to replace the file extension (to ensure '.blend'), - * no need to now because the operator ensures, - * its handy for scripts to save to a predefined name without blender editing it */ + /* note: used to replace the file extension (to ensure '.blend'), + * no need to now because the operator ensures, + * its handy for scripts to save to a predefined name without blender editing it */ - /* send the OnSave event */ - for (li = bmain->libraries.first; li; li = li->id.next) { - if (BLI_path_cmp(li->filepath, filepath) == 0) { - BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath); - return ok; - } - } + /* send the OnSave event */ + for (li = bmain->libraries.first; li; li = li->id.next) { + if (BLI_path_cmp(li->filepath, filepath) == 0) { + BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath); + return ok; + } + } - /* Call pre-save callbacks befores writing preview, that way you can generate custom file thumbnail... */ - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_PRE); + /* Call pre-save callbacks befores writing preview, that way you can generate custom file thumbnail... */ + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_PRE); - /* blend file thumbnail */ - /* save before exit_editmode, otherwise derivedmeshes for shared data corrupt #27765) */ - /* Main now can store a .blend thumbnail, useful for background mode or thumbnail customization. */ - main_thumb = thumb = bmain->blen_thumb; - if ((U.flag & USER_SAVE_PREVIEWS) && BLI_thread_is_main()) { - ibuf_thumb = blend_file_thumb(C, CTX_data_scene(C), CTX_wm_screen(C), &thumb); - } + /* blend file thumbnail */ + /* save before exit_editmode, otherwise derivedmeshes for shared data corrupt #27765) */ + /* Main now can store a .blend thumbnail, useful for background mode or thumbnail customization. */ + main_thumb = thumb = bmain->blen_thumb; + if ((U.flag & USER_SAVE_PREVIEWS) && BLI_thread_is_main()) { + ibuf_thumb = blend_file_thumb(C, CTX_data_scene(C), CTX_wm_screen(C), &thumb); + } - /* operator now handles overwrite checks */ + /* operator now handles overwrite checks */ - if (G.fileflags & G_FILE_AUTOPACK) { - packAll(bmain, reports, false); - } + if (G.fileflags & G_FILE_AUTOPACK) { + packAll(bmain, reports, false); + } - /* don't forget not to return without! */ - WM_cursor_wait(1); + /* don't forget not to return without! */ + WM_cursor_wait(1); - ED_editors_flush_edits(bmain, false); + ED_editors_flush_edits(bmain, false); - fileflags |= G_FILE_HISTORY; /* write file history */ + fileflags |= G_FILE_HISTORY; /* write file history */ - /* first time saving */ - /* XXX temp solution to solve bug, real fix coming (ton) */ - if ((BKE_main_blendfile_path(bmain)[0] == '\0') && !(fileflags & G_FILE_SAVE_COPY)) { - BLI_strncpy(bmain->name, filepath, sizeof(bmain->name)); - } + /* first time saving */ + /* XXX temp solution to solve bug, real fix coming (ton) */ + if ((BKE_main_blendfile_path(bmain)[0] == '\0') && !(fileflags & G_FILE_SAVE_COPY)) { + BLI_strncpy(bmain->name, filepath, sizeof(bmain->name)); + } - /* XXX temp solution to solve bug, real fix coming (ton) */ - bmain->recovered = 0; + /* XXX temp solution to solve bug, real fix coming (ton) */ + bmain->recovered = 0; - if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) { - const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0); + if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) { + const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0); - if (!(fileflags & G_FILE_SAVE_COPY)) { - G.relbase_valid = 1; - BLI_strncpy(bmain->name, filepath, sizeof(bmain->name)); /* is guaranteed current file */ + if (!(fileflags & G_FILE_SAVE_COPY)) { + G.relbase_valid = 1; + BLI_strncpy(bmain->name, filepath, sizeof(bmain->name)); /* is guaranteed current file */ - G.save_over = 1; /* disable untitled.blend convention */ - } + G.save_over = 1; /* disable untitled.blend convention */ + } - SET_FLAG_FROM_TEST(G.fileflags, fileflags & G_FILE_COMPRESS, G_FILE_COMPRESS); + SET_FLAG_FROM_TEST(G.fileflags, fileflags & G_FILE_COMPRESS, G_FILE_COMPRESS); - /* prevent background mode scripts from clobbering history */ - if (do_history) { - wm_history_file_update(); - } + /* prevent background mode scripts from clobbering history */ + if (do_history) { + wm_history_file_update(); + } - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_POST); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_POST); - /* run this function after because the file cant be written before the blend is */ - if (ibuf_thumb) { - IMB_thumb_delete(filepath, THB_FAIL); /* without this a failed thumb overrides */ - ibuf_thumb = IMB_thumb_create(filepath, THB_LARGE, THB_SOURCE_BLEND, ibuf_thumb); - } + /* run this function after because the file cant be written before the blend is */ + if (ibuf_thumb) { + IMB_thumb_delete(filepath, THB_FAIL); /* without this a failed thumb overrides */ + ibuf_thumb = IMB_thumb_create(filepath, THB_LARGE, THB_SOURCE_BLEND, ibuf_thumb); + } - /* Success. */ - ok = true; - } + /* Success. */ + ok = true; + } - if (ibuf_thumb) { - IMB_freeImBuf(ibuf_thumb); - } - if (thumb && thumb != main_thumb) { - MEM_freeN(thumb); - } + if (ibuf_thumb) { + IMB_freeImBuf(ibuf_thumb); + } + if (thumb && thumb != main_thumb) { + MEM_freeN(thumb); + } - WM_cursor_wait(0); + WM_cursor_wait(0); - return ok; + return ok; } /************************ autosave ****************************/ void wm_autosave_location(char *filepath) { - const int pid = abs(getpid()); - char path[1024]; + const int pid = abs(getpid()); + char path[1024]; #ifdef WIN32 - const char *savedir; + const char *savedir; #endif - if (G_MAIN && G.relbase_valid) { - const char *basename = BLI_path_basename(BKE_main_blendfile_path_from_global()); - int len = strlen(basename) - 6; - BLI_snprintf(path, sizeof(path), "%.*s (autosave).blend", len, basename); - } - else { - BLI_snprintf(path, sizeof(path), "%d (autosave).blend", pid); - } + if (G_MAIN && G.relbase_valid) { + const char *basename = BLI_path_basename(BKE_main_blendfile_path_from_global()); + int len = strlen(basename) - 6; + BLI_snprintf(path, sizeof(path), "%.*s (autosave).blend", len, basename); + } + else { + BLI_snprintf(path, sizeof(path), "%d (autosave).blend", pid); + } #ifdef WIN32 - /* XXX Need to investigate how to handle default location of '/tmp/' - * This is a relative directory on Windows, and it may be - * found. Example: - * Blender installed on D:\ drive, D:\ drive has D:\tmp\ - * Now, BLI_exists() will find '/tmp/' exists, but - * BLI_make_file_string will create string that has it most likely on C:\ - * through get_default_root(). - * If there is no C:\tmp autosave fails. */ - if (!BLI_exists(BKE_tempdir_base())) { - savedir = BKE_appdir_folder_id_create(BLENDER_USER_AUTOSAVE, NULL); - BLI_make_file_string("/", filepath, savedir, path); - return; - } + /* XXX Need to investigate how to handle default location of '/tmp/' + * This is a relative directory on Windows, and it may be + * found. Example: + * Blender installed on D:\ drive, D:\ drive has D:\tmp\ + * Now, BLI_exists() will find '/tmp/' exists, but + * BLI_make_file_string will create string that has it most likely on C:\ + * through get_default_root(). + * If there is no C:\tmp autosave fails. */ + if (!BLI_exists(BKE_tempdir_base())) { + savedir = BKE_appdir_folder_id_create(BLENDER_USER_AUTOSAVE, NULL); + BLI_make_file_string("/", filepath, savedir, path); + return; + } #endif - BLI_make_file_string("/", filepath, BKE_tempdir_base(), path); + BLI_make_file_string("/", filepath, BKE_tempdir_base(), path); } void WM_autosave_init(wmWindowManager *wm) { - wm_autosave_timer_ended(wm); + wm_autosave_timer_ended(wm); - if (U.flag & USER_AUTOSAVE) { - wm->autosavetimer = WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime * 60.0); - } + if (U.flag & USER_AUTOSAVE) { + wm->autosavetimer = WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime * 60.0); + } } void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(wt)) { - char filepath[FILE_MAX]; - - WM_event_remove_timer(wm, NULL, wm->autosavetimer); - - /* if a modal operator is running, don't autosave, but try again in 10 seconds */ - for (wmWindow *win = wm->windows.first; win; win = win->next) { - LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { - if (handler_base->type == WM_HANDLER_TYPE_OP) { - wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; - if (handler->op) { - wm->autosavetimer = WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, 10.0); - if (G.debug) { - printf("Skipping auto-save, modal operator running, retrying in ten seconds...\n"); - } - return; - } - } - } - } - - wm_autosave_location(filepath); - - if (U.uiflag & USER_GLOBALUNDO) { - /* fast save of last undobuffer, now with UI */ - struct MemFile *memfile = ED_undosys_stack_memfile_get_active(wm->undo_stack); - if (memfile) { - BLO_memfile_write_file(memfile, filepath); - } - } - else { - /* save as regular blend file */ - Main *bmain = CTX_data_main(C); - int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); - - ED_editors_flush_edits(bmain, false); - - /* Error reporting into console */ - BLO_write_file(bmain, 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); + char filepath[FILE_MAX]; + + WM_event_remove_timer(wm, NULL, wm->autosavetimer); + + /* if a modal operator is running, don't autosave, but try again in 10 seconds */ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { + if (handler_base->type == WM_HANDLER_TYPE_OP) { + wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; + if (handler->op) { + wm->autosavetimer = WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, 10.0); + if (G.debug) { + printf("Skipping auto-save, modal operator running, retrying in ten seconds...\n"); + } + return; + } + } + } + } + + wm_autosave_location(filepath); + + if (U.uiflag & USER_GLOBALUNDO) { + /* fast save of last undobuffer, now with UI */ + struct MemFile *memfile = ED_undosys_stack_memfile_get_active(wm->undo_stack); + if (memfile) { + BLO_memfile_write_file(memfile, filepath); + } + } + else { + /* save as regular blend file */ + Main *bmain = CTX_data_main(C); + int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); + + ED_editors_flush_edits(bmain, false); + + /* Error reporting into console */ + BLO_write_file(bmain, 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); } void wm_autosave_timer_ended(wmWindowManager *wm) { - if (wm->autosavetimer) { - WM_event_remove_timer(wm, NULL, wm->autosavetimer); - wm->autosavetimer = NULL; - } + if (wm->autosavetimer) { + WM_event_remove_timer(wm, NULL, wm->autosavetimer); + wm->autosavetimer = NULL; + } } void wm_autosave_delete(void) { - char filename[FILE_MAX]; + char filename[FILE_MAX]; - wm_autosave_location(filename); + wm_autosave_location(filename); - if (BLI_exists(filename)) { - char str[FILE_MAX]; - BLI_make_file_string("/", str, BKE_tempdir_base(), BLENDER_QUIT_FILE); + if (BLI_exists(filename)) { + char str[FILE_MAX]; + BLI_make_file_string("/", str, BKE_tempdir_base(), BLENDER_QUIT_FILE); - /* if global undo; remove tempsave, otherwise rename */ - if (U.uiflag & USER_GLOBALUNDO) { - BLI_delete(filename, false, false); - } - else { - BLI_rename(filename, str); - } - } + /* if global undo; remove tempsave, otherwise rename */ + if (U.uiflag & USER_GLOBALUNDO) { + BLI_delete(filename, false, false); + } + else { + BLI_rename(filename, str); + } + } } void wm_autosave_read(bContext *C, ReportList *reports) { - char filename[FILE_MAX]; + char filename[FILE_MAX]; - wm_autosave_location(filename); - WM_file_read(C, filename, reports); + wm_autosave_location(filename); + WM_file_read(C, filename, reports); } - /** \name Initialize WM_OT_open_xxx properties * * Check if load_ui was set by the caller. @@ -1497,41 +1533,38 @@ void wm_autosave_read(bContext *C, ReportList *reports) void wm_open_init_load_ui(wmOperator *op, bool use_prefs) { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "load_ui"); - if (!RNA_property_is_set(op->ptr, prop)) { - bool value = use_prefs ? - ((U.flag & USER_FILENOUI) == 0) : - ((G.fileflags & G_FILE_NO_UI) == 0); + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "load_ui"); + if (!RNA_property_is_set(op->ptr, prop)) { + bool value = use_prefs ? ((U.flag & USER_FILENOUI) == 0) : ((G.fileflags & G_FILE_NO_UI) == 0); - RNA_property_boolean_set(op->ptr, prop, value); - } + RNA_property_boolean_set(op->ptr, prop, value); + } } void wm_open_init_use_scripts(wmOperator *op, bool use_prefs) { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_scripts"); - if (!RNA_property_is_set(op->ptr, prop)) { - /* use G_FLAG_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. */ - bool value = use_prefs ? - ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) : - ((G.f & G_FLAG_SCRIPT_AUTOEXEC) != 0); + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_scripts"); + if (!RNA_property_is_set(op->ptr, prop)) { + /* use G_FLAG_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. */ + bool value = use_prefs ? ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) : + ((G.f & G_FLAG_SCRIPT_AUTOEXEC) != 0); - RNA_property_boolean_set(op->ptr, prop, value); - } + RNA_property_boolean_set(op->ptr, prop, value); + } } /** \} */ void WM_file_tag_modified(void) { - wmWindowManager *wm = G_MAIN->wm.first; - if (wm->file_saved) { - wm->file_saved = 0; - /* notifier that data changed, for save-over warning or header */ - WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL); - } + wmWindowManager *wm = G_MAIN->wm.first; + if (wm->file_saved) { + wm->file_saved = 0; + /* notifier that data changed, for save-over warning or header */ + WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL); + } } /** \name Preferences/startup save & load. @@ -1544,319 +1577,328 @@ void WM_file_tag_modified(void) */ static int wm_homefile_write_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - char filepath[FILE_MAX]; - int fileflags; + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + char filepath[FILE_MAX]; + int fileflags; - const char *app_template = U.app_template[0] ? U.app_template : NULL; - const char * const cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, app_template); - if (cfgdir == NULL) { - BKE_report(op->reports, RPT_ERROR, "Unable to create user config path"); - return OPERATOR_CANCELLED; - } + const char *app_template = U.app_template[0] ? U.app_template : NULL; + const char *const cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, app_template); + if (cfgdir == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unable to create user config path"); + return OPERATOR_CANCELLED; + } - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_PRE); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_PRE); - /* check current window and close it if temp */ - if (win && WM_window_is_temp_screen(win)) { - wm_window_close(C, wm, win); - } + /* check current window and close it if temp */ + if (win && WM_window_is_temp_screen(win)) { + wm_window_close(C, wm, win); + } - /* update keymaps in user preferences */ - WM_keyconfig_update(wm); + /* update keymaps in user preferences */ + WM_keyconfig_update(wm); - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_STARTUP_FILE, NULL); + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_STARTUP_FILE, NULL); - printf("Writing homefile: '%s' ", filepath); + printf("Writing homefile: '%s' ", filepath); - ED_editors_flush_edits(bmain, false); + ED_editors_flush_edits(bmain, false); - /* force save as regular blend file */ - fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); + /* force save as regular blend file */ + fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); - if (BLO_write_file(bmain, filepath, fileflags | G_FILE_USERPREFS, op->reports, NULL) == 0) { - printf("fail\n"); - return OPERATOR_CANCELLED; - } + if (BLO_write_file(bmain, filepath, fileflags | G_FILE_USERPREFS, op->reports, NULL) == 0) { + printf("fail\n"); + return OPERATOR_CANCELLED; + } - printf("ok\n"); + printf("ok\n"); - G.save_over = 0; + G.save_over = 0; - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_POST); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_POST); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void WM_OT_save_homefile(wmOperatorType *ot) { - ot->name = "Save Startup File"; - ot->idname = "WM_OT_save_homefile"; - ot->description = "Make the current file the default .blend file"; + ot->name = "Save Startup File"; + ot->idname = "WM_OT_save_homefile"; + ot->description = "Make the current file the default .blend file"; - ot->invoke = WM_operator_confirm; - ot->exec = wm_homefile_write_exec; + ot->invoke = WM_operator_confirm; + ot->exec = wm_homefile_write_exec; } static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { - bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); - BLI_addtail(&U.autoexec_paths, path_cmp); - return OPERATOR_FINISHED; + bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); + BLI_addtail(&U.autoexec_paths, path_cmp); + return OPERATOR_FINISHED; } void WM_OT_userpref_autoexec_path_add(wmOperatorType *ot) { - ot->name = "Add Autoexec Path"; - ot->idname = "WM_OT_userpref_autoexec_path_add"; - ot->description = "Add path to exclude from autoexecution"; + ot->name = "Add Autoexec Path"; + ot->idname = "WM_OT_userpref_autoexec_path_add"; + ot->description = "Add path to exclude from autoexecution"; - ot->exec = wm_userpref_autoexec_add_exec; + ot->exec = wm_userpref_autoexec_add_exec; - ot->flag = OPTYPE_INTERNAL; + ot->flag = OPTYPE_INTERNAL; } static int wm_userpref_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op) { - const int index = RNA_int_get(op->ptr, "index"); - bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index); - if (path_cmp) { - BLI_freelinkN(&U.autoexec_paths, path_cmp); - } - return OPERATOR_FINISHED; + const int index = RNA_int_get(op->ptr, "index"); + bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index); + if (path_cmp) { + BLI_freelinkN(&U.autoexec_paths, path_cmp); + } + return OPERATOR_FINISHED; } void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot) { - ot->name = "Remove Autoexec Path"; - ot->idname = "WM_OT_userpref_autoexec_path_remove"; - ot->description = "Remove path to exclude from autoexecution"; + ot->name = "Remove Autoexec Path"; + ot->idname = "WM_OT_userpref_autoexec_path_remove"; + ot->description = "Remove path to exclude from autoexecution"; - ot->exec = wm_userpref_autoexec_remove_exec; + ot->exec = wm_userpref_autoexec_remove_exec; - ot->flag = OPTYPE_INTERNAL; + ot->flag = OPTYPE_INTERNAL; - RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); } /* Only save the prefs block. operator entry */ static int wm_userpref_write_exec(bContext *C, wmOperator *op) { - wmWindowManager *wm = CTX_wm_manager(C); - char filepath[FILE_MAX]; - const char *cfgdir; - bool ok = true; - bool use_template_userpref = wm_app_template_has_userpref(U.app_template); - - /* update keymaps in user preferences */ - WM_keyconfig_update(wm); - - if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) { - bool ok_write; - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); - - printf("Writing userprefs: '%s' ", filepath); - if (use_template_userpref) { - ok_write = BKE_blendfile_userdef_write_app_template(filepath, op->reports); - } - else { - ok_write = BKE_blendfile_userdef_write(filepath, op->reports); - } - - if (ok_write) { - printf("ok\n"); - } - else { - printf("fail\n"); - ok = false; - } - } - else { - BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path"); - } - - if (use_template_userpref) { - if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { - /* Also save app-template prefs */ - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); - - printf("Writing userprefs app-template: '%s' ", filepath); - if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) { - printf("ok\n"); - } - else { - printf("fail\n"); - ok = false; - } - } - else { - BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path"); - ok = false; - } - } - - return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + wmWindowManager *wm = CTX_wm_manager(C); + char filepath[FILE_MAX]; + const char *cfgdir; + bool ok = true; + bool use_template_userpref = wm_app_template_has_userpref(U.app_template); + + /* update keymaps in user preferences */ + WM_keyconfig_update(wm); + + if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) { + bool ok_write; + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + + printf("Writing userprefs: '%s' ", filepath); + if (use_template_userpref) { + ok_write = BKE_blendfile_userdef_write_app_template(filepath, op->reports); + } + else { + ok_write = BKE_blendfile_userdef_write(filepath, op->reports); + } + + if (ok_write) { + printf("ok\n"); + } + else { + printf("fail\n"); + ok = false; + } + } + else { + BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path"); + } + + if (use_template_userpref) { + if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { + /* Also save app-template prefs */ + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + + printf("Writing userprefs app-template: '%s' ", filepath); + if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) { + printf("ok\n"); + } + else { + printf("fail\n"); + ok = false; + } + } + else { + BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path"); + ok = false; + } + } + + return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } void WM_OT_save_userpref(wmOperatorType *ot) { - ot->name = "Save Preferences"; - ot->idname = "WM_OT_save_userpref"; - ot->description = "Save preferences separately, overrides startup file preferences"; + ot->name = "Save Preferences"; + ot->idname = "WM_OT_save_userpref"; + ot->description = "Save preferences separately, overrides startup file preferences"; - ot->invoke = WM_operator_confirm; - ot->exec = wm_userpref_write_exec; + ot->invoke = WM_operator_confirm; + ot->exec = wm_userpref_write_exec; } static int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { - ED_file_read_bookmarks(); - wm_history_file_read(); - return OPERATOR_FINISHED; + ED_file_read_bookmarks(); + wm_history_file_read(); + return OPERATOR_FINISHED; } void WM_OT_read_history(wmOperatorType *ot) { - ot->name = "Reload History File"; - ot->idname = "WM_OT_read_history"; - ot->description = "Reloads history and bookmarks"; + ot->name = "Reload History File"; + ot->idname = "WM_OT_read_history"; + ot->description = "Reloads history and bookmarks"; - ot->invoke = WM_operator_confirm; - ot->exec = wm_history_file_read_exec; + ot->invoke = WM_operator_confirm; + ot->exec = wm_history_file_read_exec; - /* this operator is only used for loading settings from a previous blender install */ - ot->flag = OPTYPE_INTERNAL; + /* this operator is only used for loading settings from a previous blender install */ + ot->flag = OPTYPE_INTERNAL; } static int wm_homefile_read_exec(bContext *C, wmOperator *op) { - const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings")); - bool use_userdef = false; - char filepath_buf[FILE_MAX]; - const char *filepath = NULL; - - if (!use_factory_settings) { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath"); - - /* This can be used when loading of a start-up file should only change - * the scene content but keep the blender UI as it is. */ - wm_open_init_load_ui(op, true); - SET_FLAG_FROM_TEST(G.fileflags, !RNA_boolean_get(op->ptr, "load_ui"), G_FILE_NO_UI); - - if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_string_get(op->ptr, prop, filepath_buf); - filepath = filepath_buf; - if (BLI_access(filepath, R_OK)) { - BKE_reportf(op->reports, RPT_ERROR, "Can't read alternative start-up file: '%s'", filepath); - return OPERATOR_CANCELLED; - } - } - } - else { - /* always load UI for factory settings (prefs will re-init) */ - G.fileflags &= ~G_FILE_NO_UI; - /* Always load preferences with factory settings. */ - use_userdef = true; - } - - char app_template_buf[sizeof(U.app_template)]; - const char *app_template; - PropertyRNA *prop_app_template = RNA_struct_find_property(op->ptr, "app_template"); - const bool use_splash = !use_factory_settings && RNA_boolean_get(op->ptr, "use_splash"); - const bool use_empty_data = RNA_boolean_get(op->ptr, "use_empty"); - - if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) { - RNA_property_string_get(op->ptr, prop_app_template, app_template_buf); - app_template = app_template_buf; - - /* Always load preferences when switching templates with own preferences. */ - use_userdef = wm_app_template_has_userpref(app_template) || - wm_app_template_has_userpref(U.app_template); - - /* Turn override off, since we're explicitly loading a different app-template. */ - WM_init_state_app_template_set(NULL); - } - else { - /* Normally NULL, only set when overriding from the command-line. */ - app_template = WM_init_state_app_template_get(); - } - - wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, use_userdef, filepath, app_template, NULL); - if (use_splash) { - WM_init_splash(C); - } - return OPERATOR_FINISHED; -} - -static int wm_homefile_read_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - /* Draw menu which includes default startup and application templates. */ - uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("New File"), ICON_FILE_NEW); - uiLayout *layout = UI_popup_menu_layout(pup); - - MenuType *mt = WM_menutype_find("TOPBAR_MT_file_new", false); - if (mt) { - UI_menutype_draw(C, mt, layout); - } - - UI_popup_menu_end(C, pup); - - return OPERATOR_INTERFACE; + const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings")); + bool use_userdef = false; + char filepath_buf[FILE_MAX]; + const char *filepath = NULL; + + if (!use_factory_settings) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath"); + + /* This can be used when loading of a start-up file should only change + * the scene content but keep the blender UI as it is. */ + wm_open_init_load_ui(op, true); + SET_FLAG_FROM_TEST(G.fileflags, !RNA_boolean_get(op->ptr, "load_ui"), G_FILE_NO_UI); + + if (RNA_property_is_set(op->ptr, prop)) { + RNA_property_string_get(op->ptr, prop, filepath_buf); + filepath = filepath_buf; + if (BLI_access(filepath, R_OK)) { + BKE_reportf( + op->reports, RPT_ERROR, "Can't read alternative start-up file: '%s'", filepath); + return OPERATOR_CANCELLED; + } + } + } + else { + /* always load UI for factory settings (prefs will re-init) */ + G.fileflags &= ~G_FILE_NO_UI; + /* Always load preferences with factory settings. */ + use_userdef = true; + } + + char app_template_buf[sizeof(U.app_template)]; + const char *app_template; + PropertyRNA *prop_app_template = RNA_struct_find_property(op->ptr, "app_template"); + const bool use_splash = !use_factory_settings && RNA_boolean_get(op->ptr, "use_splash"); + const bool use_empty_data = RNA_boolean_get(op->ptr, "use_empty"); + + if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) { + RNA_property_string_get(op->ptr, prop_app_template, app_template_buf); + app_template = app_template_buf; + + /* Always load preferences when switching templates with own preferences. */ + use_userdef = wm_app_template_has_userpref(app_template) || + wm_app_template_has_userpref(U.app_template); + + /* Turn override off, since we're explicitly loading a different app-template. */ + WM_init_state_app_template_set(NULL); + } + else { + /* Normally NULL, only set when overriding from the command-line. */ + app_template = WM_init_state_app_template_get(); + } + + wm_homefile_read(C, + op->reports, + use_factory_settings, + use_empty_data, + use_userdef, + filepath, + app_template, + NULL); + if (use_splash) { + WM_init_splash(C); + } + return OPERATOR_FINISHED; +} + +static int wm_homefile_read_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *UNUSED(event)) +{ + /* Draw menu which includes default startup and application templates. */ + uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("New File"), ICON_FILE_NEW); + uiLayout *layout = UI_popup_menu_layout(pup); + + MenuType *mt = WM_menutype_find("TOPBAR_MT_file_new", false); + if (mt) { + UI_menutype_draw(C, mt, layout); + } + + UI_popup_menu_end(C, pup); + + return OPERATOR_INTERFACE; } void WM_OT_read_homefile(wmOperatorType *ot) { - PropertyRNA *prop; - ot->name = "Reload Start-Up File"; - ot->idname = "WM_OT_read_homefile"; - ot->description = "Open the default file (doesn't save the current file)"; + PropertyRNA *prop; + ot->name = "Reload Start-Up File"; + ot->idname = "WM_OT_read_homefile"; + ot->description = "Open the default file (doesn't save the current file)"; - ot->invoke = wm_homefile_read_invoke; - ot->exec = wm_homefile_read_exec; + ot->invoke = wm_homefile_read_invoke; + ot->exec = wm_homefile_read_exec; - prop = RNA_def_string_file_path(ot->srna, "filepath", NULL, - FILE_MAX, "File Path", - "Path to an alternative start-up file"); - RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_string_file_path( + ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Path to an alternative start-up file"); + RNA_def_property_flag(prop, PROP_HIDDEN); - /* So scripts can use an alternative start-up file without the UI */ - prop = RNA_def_boolean(ot->srna, "load_ui", true, "Load UI", - "Load user interface setup from the .blend file"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* So scripts can use an alternative start-up file without the UI */ + prop = RNA_def_boolean( + ot->srna, "load_ui", true, "Load UI", "Load user interface setup from the .blend file"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - /* So the splash can be kept open after loading a file (for templates). */ - prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* So the splash can be kept open after loading a file (for templates). */ + prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - /* omit poll to run in background mode */ + /* omit poll to run in background mode */ } void WM_OT_read_factory_settings(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - ot->name = "Load Factory Settings"; - ot->idname = "WM_OT_read_factory_settings"; - ot->description = "Load default file and preferences"; + ot->name = "Load Factory Settings"; + ot->idname = "WM_OT_read_factory_settings"; + ot->description = "Load default file and preferences"; - ot->invoke = WM_operator_confirm; - ot->exec = wm_homefile_read_exec; + ot->invoke = WM_operator_confirm; + ot->exec = wm_homefile_read_exec; - prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - /* omit poll to run in background mode */ + /* omit poll to run in background mode */ } /** \} */ @@ -1868,167 +1910,178 @@ void WM_OT_read_factory_settings(wmOperatorType *ot) /** * Wrap #WM_file_read, shared by file reading operators. */ -static bool wm_file_read_opwrap(bContext *C, const char *filepath, ReportList *reports, +static bool wm_file_read_opwrap(bContext *C, + const char *filepath, + ReportList *reports, const bool autoexec_init) { - bool success; + bool success; - /* XXX wm in context is not set correctly after WM_file_read -> crash */ - /* do it before for now, but is this correct with multiple windows? */ - WM_event_add_notifier(C, NC_WINDOW, NULL); + /* XXX wm in context is not set correctly after WM_file_read -> crash */ + /* do it before for now, but is this correct with multiple windows? */ + WM_event_add_notifier(C, NC_WINDOW, NULL); - if (autoexec_init) { - WM_file_autoexec_init(filepath); - } + if (autoexec_init) { + WM_file_autoexec_init(filepath); + } - success = WM_file_read(C, filepath, reports); + success = WM_file_read(C, filepath, reports); - return success; + return success; } /* currently fits in a pointer */ struct FileRuntime { - bool is_untrusted; + bool is_untrusted; }; static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Main *bmain = CTX_data_main(C); - const char *openname = BKE_main_blendfile_path(bmain); + Main *bmain = CTX_data_main(C); + const char *openname = BKE_main_blendfile_path(bmain); - 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 (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; - openname = recent->filepath; - } + /* if possible, get the name of the most recently used .blend file */ + if (G.recent_files.first) { + struct RecentFile *recent = G.recent_files.first; + openname = recent->filepath; + } - RNA_string_set(op->ptr, "filepath", openname); - wm_open_init_load_ui(op, true); - wm_open_init_use_scripts(op, true); - op->customdata = NULL; + RNA_string_set(op->ptr, "filepath", openname); + wm_open_init_load_ui(op, true); + wm_open_init_use_scripts(op, true); + op->customdata = NULL; - WM_event_add_fileselect(C, op); + WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } static int wm_open_mainfile_exec(bContext *C, wmOperator *op) { - char filepath[FILE_MAX]; - bool success; + char filepath[FILE_MAX]; + bool success; - RNA_string_get(op->ptr, "filepath", filepath); + RNA_string_get(op->ptr, "filepath", filepath); - /* re-use last loaded setting so we can reload a file without changing */ - wm_open_init_load_ui(op, false); - wm_open_init_use_scripts(op, false); + /* re-use last loaded setting so we can reload a file without changing */ + wm_open_init_load_ui(op, false); + wm_open_init_use_scripts(op, false); - if (RNA_boolean_get(op->ptr, "load_ui")) { - G.fileflags &= ~G_FILE_NO_UI; - } - else { - G.fileflags |= G_FILE_NO_UI; - } + if (RNA_boolean_get(op->ptr, "load_ui")) { + G.fileflags &= ~G_FILE_NO_UI; + } + else { + G.fileflags |= G_FILE_NO_UI; + } - if (RNA_boolean_get(op->ptr, "use_scripts")) { - G.f |= G_FLAG_SCRIPT_AUTOEXEC; - } - else { - G.f &= ~G_FLAG_SCRIPT_AUTOEXEC; - } + if (RNA_boolean_get(op->ptr, "use_scripts")) { + G.f |= G_FLAG_SCRIPT_AUTOEXEC; + } + else { + G.f &= ~G_FLAG_SCRIPT_AUTOEXEC; + } - success = wm_file_read_opwrap(C, filepath, op->reports, !(G.f & G_FLAG_SCRIPT_AUTOEXEC)); + success = wm_file_read_opwrap(C, filepath, op->reports, !(G.f & G_FLAG_SCRIPT_AUTOEXEC)); - /* for file open also popup for warnings, not only errors */ - BKE_report_print_level_set(op->reports, RPT_WARNING); + /* for file open also popup for warnings, not only errors */ + BKE_report_print_level_set(op->reports, RPT_WARNING); - if (success) { - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + if (success) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } static bool wm_open_mainfile_check(bContext *UNUSED(C), wmOperator *op) { - struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_scripts"); - bool is_untrusted = false; - char path[FILE_MAX]; - char *lslash; + struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_scripts"); + bool is_untrusted = false; + char path[FILE_MAX]; + char *lslash; - RNA_string_get(op->ptr, "filepath", path); + RNA_string_get(op->ptr, "filepath", path); - /* get the dir */ - lslash = (char *)BLI_last_slash(path); - if (lslash) { - *(lslash + 1) = '\0'; - } + /* get the dir */ + lslash = (char *)BLI_last_slash(path); + if (lslash) { + *(lslash + 1) = '\0'; + } - if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) { - if (BKE_autoexec_match(path) == true) { - RNA_property_boolean_set(op->ptr, prop, false); - is_untrusted = true; - } - } + if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) { + if (BKE_autoexec_match(path) == true) { + RNA_property_boolean_set(op->ptr, prop, false); + is_untrusted = true; + } + } - if (file_info) { - file_info->is_untrusted = is_untrusted; - } + if (file_info) { + file_info->is_untrusted = is_untrusted; + } - return is_untrusted; + return is_untrusted; } static void wm_open_mainfile_ui(bContext *UNUSED(C), wmOperator *op) { - struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; - uiLayout *layout = op->layout; - uiLayout *col = op->layout; - const char *autoexec_text; + struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; + uiLayout *layout = op->layout; + uiLayout *col = op->layout; + const char *autoexec_text; - uiItemR(layout, op->ptr, "load_ui", 0, NULL, ICON_NONE); + uiItemR(layout, op->ptr, "load_ui", 0, NULL, ICON_NONE); - col = uiLayoutColumn(layout, false); - if (file_info->is_untrusted) { - autoexec_text = IFACE_("Trusted Source [Untrusted Path]"); - uiLayoutSetActive(col, false); - uiLayoutSetEnabled(col, false); - } - else { - autoexec_text = IFACE_("Trusted Source"); - } + col = uiLayoutColumn(layout, false); + if (file_info->is_untrusted) { + autoexec_text = IFACE_("Trusted Source [Untrusted Path]"); + uiLayoutSetActive(col, false); + uiLayoutSetEnabled(col, false); + } + else { + autoexec_text = IFACE_("Trusted Source"); + } - uiItemR(col, op->ptr, "use_scripts", 0, autoexec_text, ICON_NONE); + uiItemR(col, op->ptr, "use_scripts", 0, autoexec_text, ICON_NONE); } void WM_OT_open_mainfile(wmOperatorType *ot) { - ot->name = "Open Blender File"; - ot->idname = "WM_OT_open_mainfile"; - ot->description = "Open a Blender file"; - - ot->invoke = wm_open_mainfile_invoke; - ot->exec = wm_open_mainfile_exec; - ot->check = wm_open_mainfile_check; - ot->ui = wm_open_mainfile_ui; - /* omit window poll so this can work in background mode */ - - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE, - WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - - RNA_def_boolean(ot->srna, "load_ui", true, "Load UI", "Load user interface setup in the .blend file"); - RNA_def_boolean(ot->srna, "use_scripts", true, "Trusted Source", - "Allow .blend file to execute scripts automatically, default available from system preferences"); + ot->name = "Open Blender File"; + ot->idname = "WM_OT_open_mainfile"; + ot->description = "Open a Blender file"; + + ot->invoke = wm_open_mainfile_invoke; + ot->exec = wm_open_mainfile_exec; + ot->check = wm_open_mainfile_check; + ot->ui = wm_open_mainfile_ui; + /* omit window poll so this can work in background mode */ + + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, + FILE_BLENDER, + FILE_OPENFILE, + WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); + + RNA_def_boolean( + ot->srna, "load_ui", true, "Load UI", "Load user interface setup in the .blend file"); + RNA_def_boolean(ot->srna, + "use_scripts", + true, + "Trusted Source", + "Allow .blend file to execute scripts automatically, default available from " + "system preferences"); } /** \} */ @@ -2039,47 +2092,51 @@ void WM_OT_open_mainfile(wmOperatorType *ot) static int wm_revert_mainfile_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - bool success; - char filepath[FILE_MAX]; + Main *bmain = CTX_data_main(C); + bool success; + char filepath[FILE_MAX]; - wm_open_init_use_scripts(op, false); + wm_open_init_use_scripts(op, false); - if (RNA_boolean_get(op->ptr, "use_scripts")) { - G.f |= G_FLAG_SCRIPT_AUTOEXEC; - } - else { - G.f &= ~G_FLAG_SCRIPT_AUTOEXEC; - } + if (RNA_boolean_get(op->ptr, "use_scripts")) { + G.f |= G_FLAG_SCRIPT_AUTOEXEC; + } + else { + G.f &= ~G_FLAG_SCRIPT_AUTOEXEC; + } - BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); - success = wm_file_read_opwrap(C, filepath, op->reports, !(G.f & G_FLAG_SCRIPT_AUTOEXEC)); + BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); + success = wm_file_read_opwrap(C, filepath, op->reports, !(G.f & G_FLAG_SCRIPT_AUTOEXEC)); - if (success) { - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + if (success) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } static bool wm_revert_mainfile_poll(bContext *UNUSED(C)) { - return G.relbase_valid; + return G.relbase_valid; } void WM_OT_revert_mainfile(wmOperatorType *ot) { - ot->name = "Revert"; - ot->idname = "WM_OT_revert_mainfile"; - ot->description = "Reload the saved file"; - ot->invoke = WM_operator_confirm; + ot->name = "Revert"; + ot->idname = "WM_OT_revert_mainfile"; + ot->description = "Reload the saved file"; + ot->invoke = WM_operator_confirm; - RNA_def_boolean(ot->srna, "use_scripts", true, "Trusted Source", - "Allow .blend file to execute scripts automatically, default available from system preferences"); + RNA_def_boolean(ot->srna, + "use_scripts", + true, + "Trusted Source", + "Allow .blend file to execute scripts automatically, default available from " + "system preferences"); - ot->exec = wm_revert_mainfile_exec; - ot->poll = wm_revert_mainfile_poll; + ot->exec = wm_revert_mainfile_exec; + ot->poll = wm_revert_mainfile_poll; } /** \} */ @@ -2090,90 +2147,93 @@ void WM_OT_revert_mainfile(wmOperatorType *ot) void WM_recover_last_session(bContext *C, ReportList *reports) { - char filepath[FILE_MAX]; - - BLI_make_file_string("/", filepath, BKE_tempdir_base(), BLENDER_QUIT_FILE); - /* if reports==NULL, it's called directly without operator, we add a quick check here */ - if (reports || BLI_exists(filepath)) { - G.fileflags |= G_FILE_RECOVER; + char filepath[FILE_MAX]; - wm_file_read_opwrap(C, filepath, reports, true); + BLI_make_file_string("/", filepath, BKE_tempdir_base(), BLENDER_QUIT_FILE); + /* if reports==NULL, it's called directly without operator, we add a quick check here */ + if (reports || BLI_exists(filepath)) { + G.fileflags |= G_FILE_RECOVER; - G.fileflags &= ~G_FILE_RECOVER; + wm_file_read_opwrap(C, filepath, reports, true); - /* XXX bad global... fixme */ - Main *bmain = CTX_data_main(C); - if (BKE_main_blendfile_path(bmain)[0] != '\0') { - G.file_loaded = 1; /* prevents splash to show */ - } - else { - G.relbase_valid = 0; - G.save_over = 0; /* start with save preference untitled.blend */ - } + G.fileflags &= ~G_FILE_RECOVER; - } + /* XXX bad global... fixme */ + Main *bmain = CTX_data_main(C); + if (BKE_main_blendfile_path(bmain)[0] != '\0') { + G.file_loaded = 1; /* prevents splash to show */ + } + else { + G.relbase_valid = 0; + G.save_over = 0; /* start with save preference untitled.blend */ + } + } } static int wm_recover_last_session_exec(bContext *C, wmOperator *op) { - WM_recover_last_session(C, op->reports); - return OPERATOR_FINISHED; + WM_recover_last_session(C, op->reports); + return OPERATOR_FINISHED; } void WM_OT_recover_last_session(wmOperatorType *ot) { - ot->name = "Recover Last Session"; - ot->idname = "WM_OT_recover_last_session"; - ot->description = "Open the last closed file (\"" BLENDER_QUIT_FILE "\")"; - ot->invoke = WM_operator_confirm; + ot->name = "Recover Last Session"; + ot->idname = "WM_OT_recover_last_session"; + ot->description = "Open the last closed file (\"" BLENDER_QUIT_FILE "\")"; + ot->invoke = WM_operator_confirm; - ot->exec = wm_recover_last_session_exec; + ot->exec = wm_recover_last_session_exec; } static int wm_recover_auto_save_exec(bContext *C, wmOperator *op) { - char filepath[FILE_MAX]; - bool success; + char filepath[FILE_MAX]; + bool success; - RNA_string_get(op->ptr, "filepath", filepath); + RNA_string_get(op->ptr, "filepath", filepath); - G.fileflags |= G_FILE_RECOVER; + G.fileflags |= G_FILE_RECOVER; - success = wm_file_read_opwrap(C, filepath, op->reports, true); + success = wm_file_read_opwrap(C, filepath, op->reports, true); - G.fileflags &= ~G_FILE_RECOVER; + G.fileflags &= ~G_FILE_RECOVER; - if (success) { - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + if (success) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } static int wm_recover_auto_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - char filename[FILE_MAX]; + char filename[FILE_MAX]; - wm_autosave_location(filename); - RNA_string_set(op->ptr, "filepath", filename); - WM_event_add_fileselect(C, op); + wm_autosave_location(filename); + RNA_string_set(op->ptr, "filepath", filename); + WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } void WM_OT_recover_auto_save(wmOperatorType *ot) { - ot->name = "Recover Auto Save"; - ot->idname = "WM_OT_recover_auto_save"; - ot->description = "Open an automatically saved file to recover it"; + ot->name = "Recover Auto Save"; + ot->idname = "WM_OT_recover_auto_save"; + ot->description = "Open an automatically saved file to recover it"; - ot->exec = wm_recover_auto_save_exec; - ot->invoke = wm_recover_auto_save_invoke; + ot->exec = wm_recover_auto_save_exec; + ot->invoke = wm_recover_auto_save_invoke; - WM_operator_properties_filesel( - ot, FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE, - WM_FILESEL_FILEPATH, FILE_LONGDISPLAY, FILE_SORT_TIME); + WM_operator_properties_filesel(ot, + FILE_TYPE_BLENDER, + FILE_BLENDER, + FILE_OPENFILE, + WM_FILESEL_FILEPATH, + FILE_LONGDISPLAY, + FILE_SORT_TIME); } /** \} */ @@ -2184,211 +2244,224 @@ void WM_OT_recover_auto_save(wmOperatorType *ot) static void wm_filepath_default(char *filepath) { - if (G.save_over == false) { - BLI_ensure_filename(filepath, FILE_MAX, "untitled.blend"); - } + if (G.save_over == false) { + BLI_ensure_filename(filepath, FILE_MAX, "untitled.blend"); + } } static void save_set_compress(wmOperator *op) { - PropertyRNA *prop; + PropertyRNA *prop; - prop = RNA_struct_find_property(op->ptr, "compress"); - if (!RNA_property_is_set(op->ptr, prop)) { - if (G.save_over) { /* keep flag for existing file */ - RNA_property_boolean_set(op->ptr, prop, (G.fileflags & G_FILE_COMPRESS) != 0); - } - else { /* use userdef for new file */ - RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_FILECOMPRESS) != 0); - } - } + prop = RNA_struct_find_property(op->ptr, "compress"); + if (!RNA_property_is_set(op->ptr, prop)) { + if (G.save_over) { /* keep flag for existing file */ + RNA_property_boolean_set(op->ptr, prop, (G.fileflags & G_FILE_COMPRESS) != 0); + } + else { /* use userdef for new file */ + RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_FILECOMPRESS) != 0); + } + } } static void save_set_filepath(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - PropertyRNA *prop; - char name[FILE_MAX]; + Main *bmain = CTX_data_main(C); + PropertyRNA *prop; + char name[FILE_MAX]; - prop = RNA_struct_find_property(op->ptr, "filepath"); - if (!RNA_property_is_set(op->ptr, prop)) { - /* if not saved before, get the name of the most recently used .blend file */ - if (BKE_main_blendfile_path(bmain)[0] == '\0' && G.recent_files.first) { - struct RecentFile *recent = G.recent_files.first; - BLI_strncpy(name, recent->filepath, FILE_MAX); - } - else { - BLI_strncpy(name, bmain->name, FILE_MAX); - } + prop = RNA_struct_find_property(op->ptr, "filepath"); + if (!RNA_property_is_set(op->ptr, prop)) { + /* if not saved before, get the name of the most recently used .blend file */ + if (BKE_main_blendfile_path(bmain)[0] == '\0' && G.recent_files.first) { + struct RecentFile *recent = G.recent_files.first; + BLI_strncpy(name, recent->filepath, FILE_MAX); + } + else { + BLI_strncpy(name, bmain->name, FILE_MAX); + } - wm_filepath_default(name); - RNA_property_string_set(op->ptr, prop, name); - } + wm_filepath_default(name); + RNA_property_string_set(op->ptr, prop, name); + } } static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - save_set_compress(op); - save_set_filepath(C, op); + save_set_compress(op); + save_set_filepath(C, op); - WM_event_add_fileselect(C, op); + WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } /* function used for WM_OT_save_mainfile too */ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - char path[FILE_MAX]; - const bool is_save_as = (op->type->invoke == wm_save_as_mainfile_invoke); + Main *bmain = CTX_data_main(C); + char path[FILE_MAX]; + const bool is_save_as = (op->type->invoke == wm_save_as_mainfile_invoke); - save_set_compress(op); + save_set_compress(op); - if (RNA_struct_property_is_set(op->ptr, "filepath")) { - RNA_string_get(op->ptr, "filepath", path); - } - else { - BLI_strncpy(path, BKE_main_blendfile_path(bmain), FILE_MAX); - wm_filepath_default(path); - } + if (RNA_struct_property_is_set(op->ptr, "filepath")) { + RNA_string_get(op->ptr, "filepath", path); + } + else { + BLI_strncpy(path, BKE_main_blendfile_path(bmain), FILE_MAX); + wm_filepath_default(path); + } - const int fileflags_orig = G.fileflags; - int fileflags = G.fileflags & ~G_FILE_USERPREFS; + const int fileflags_orig = G.fileflags; + int fileflags = G.fileflags & ~G_FILE_USERPREFS; - /* set compression flag */ - SET_FLAG_FROM_TEST( - fileflags, RNA_boolean_get(op->ptr, "compress"), - G_FILE_COMPRESS); - SET_FLAG_FROM_TEST( - fileflags, RNA_boolean_get(op->ptr, "relative_remap"), - G_FILE_RELATIVE_REMAP); - SET_FLAG_FROM_TEST( - fileflags, - (RNA_struct_property_is_set(op->ptr, "copy") && - RNA_boolean_get(op->ptr, "copy")), - G_FILE_SAVE_COPY); + /* set compression flag */ + SET_FLAG_FROM_TEST(fileflags, RNA_boolean_get(op->ptr, "compress"), G_FILE_COMPRESS); + SET_FLAG_FROM_TEST(fileflags, RNA_boolean_get(op->ptr, "relative_remap"), G_FILE_RELATIVE_REMAP); + SET_FLAG_FROM_TEST( + fileflags, + (RNA_struct_property_is_set(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy")), + G_FILE_SAVE_COPY); - const bool ok = wm_file_write(C, path, fileflags, op->reports); + const bool ok = wm_file_write(C, path, fileflags, op->reports); - if ((op->flag & OP_IS_INVOKE) == 0) { - /* OP_IS_INVOKE is set when the operator is called from the GUI. - * If it is not set, the operator is called from a script and - * shouldn't influence G.fileflags. */ - G.fileflags = fileflags_orig; - } + if ((op->flag & OP_IS_INVOKE) == 0) { + /* OP_IS_INVOKE is set when the operator is called from the GUI. + * If it is not set, the operator is called from a script and + * shouldn't influence G.fileflags. */ + G.fileflags = fileflags_orig; + } - if (ok == false) { - return OPERATOR_CANCELLED; - } + if (ok == false) { + return OPERATOR_CANCELLED; + } - WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL); + WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL); - if (!is_save_as && RNA_boolean_get(op->ptr, "exit")) { - wm_exit_schedule_delayed(C); - } + if (!is_save_as && RNA_boolean_get(op->ptr, "exit")) { + wm_exit_schedule_delayed(C); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } /* function used for WM_OT_save_mainfile too */ static bool blend_save_check(bContext *UNUSED(C), wmOperator *op) { - char filepath[FILE_MAX]; - RNA_string_get(op->ptr, "filepath", filepath); - if (!BLO_has_bfile_extension(filepath)) { - /* some users would prefer BLI_path_extension_replace(), - * we keep getting nitpicking bug reports about this - campbell */ - BLI_path_extension_ensure(filepath, FILE_MAX, ".blend"); - RNA_string_set(op->ptr, "filepath", filepath); - return true; - } - return false; + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); + if (!BLO_has_bfile_extension(filepath)) { + /* some users would prefer BLI_path_extension_replace(), + * we keep getting nitpicking bug reports about this - campbell */ + BLI_path_extension_ensure(filepath, FILE_MAX, ".blend"); + RNA_string_set(op->ptr, "filepath", filepath); + return true; + } + return false; } void WM_OT_save_as_mainfile(wmOperatorType *ot) { - PropertyRNA *prop; - - ot->name = "Save As Blender File"; - ot->idname = "WM_OT_save_as_mainfile"; - ot->description = "Save the current file in the desired location"; - - ot->invoke = wm_save_as_mainfile_invoke; - ot->exec = wm_save_as_mainfile_exec; - ot->check = blend_save_check; - /* omit window poll so this can work in background mode */ - - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE, - WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file"); - RNA_def_boolean(ot->srna, "relative_remap", true, "Remap Relative", - "Make paths relative when saving to a different directory"); - prop = RNA_def_boolean(ot->srna, "copy", false, "Save Copy", - "Save a copy of the actual working state but does not make saved file active"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + ot->name = "Save As Blender File"; + ot->idname = "WM_OT_save_as_mainfile"; + ot->description = "Save the current file in the desired location"; + + ot->invoke = wm_save_as_mainfile_invoke; + ot->exec = wm_save_as_mainfile_exec; + ot->check = blend_save_check; + /* omit window poll so this can work in background mode */ + + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, + FILE_BLENDER, + FILE_SAVE, + WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); + RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file"); + RNA_def_boolean(ot->srna, + "relative_remap", + true, + "Remap Relative", + "Make paths relative when saving to a different directory"); + prop = RNA_def_boolean( + ot->srna, + "copy", + false, + "Save Copy", + "Save a copy of the actual working state but does not make saved file active"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - int ret; + int ret; - /* cancel if no active window */ - if (CTX_wm_window(C) == NULL) { - return OPERATOR_CANCELLED; - } + /* cancel if no active window */ + if (CTX_wm_window(C) == NULL) { + return OPERATOR_CANCELLED; + } - save_set_compress(op); - save_set_filepath(C, op); + save_set_compress(op); + save_set_filepath(C, op); - /* if we're saving for the first time and prefer relative paths - any existing paths will be absolute, - * enable the option to remap paths to avoid confusion [#37240] */ - if ((G.relbase_valid == false) && (U.flag & USER_RELPATHS)) { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "relative_remap"); - if (!RNA_property_is_set(op->ptr, prop)) { - RNA_property_boolean_set(op->ptr, prop, true); - } - } + /* if we're saving for the first time and prefer relative paths - any existing paths will be absolute, + * enable the option to remap paths to avoid confusion [#37240] */ + if ((G.relbase_valid == false) && (U.flag & USER_RELPATHS)) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "relative_remap"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_set(op->ptr, prop, true); + } + } - if (G.save_over) { - char path[FILE_MAX]; + if (G.save_over) { + char path[FILE_MAX]; - RNA_string_get(op->ptr, "filepath", path); - ret = wm_save_as_mainfile_exec(C, op); - /* Without this there is no feedback the file was saved. */ - BKE_reportf(op->reports, RPT_INFO, "Saved \"%s\"", BLI_path_basename(path)); - } - else { - WM_event_add_fileselect(C, op); - ret = OPERATOR_RUNNING_MODAL; - } + RNA_string_get(op->ptr, "filepath", path); + ret = wm_save_as_mainfile_exec(C, op); + /* Without this there is no feedback the file was saved. */ + BKE_reportf(op->reports, RPT_INFO, "Saved \"%s\"", BLI_path_basename(path)); + } + else { + WM_event_add_fileselect(C, op); + ret = OPERATOR_RUNNING_MODAL; + } - return ret; + return ret; } void WM_OT_save_mainfile(wmOperatorType *ot) { - ot->name = "Save Blender File"; - ot->idname = "WM_OT_save_mainfile"; - ot->description = "Save the current Blender file"; - - ot->invoke = wm_save_mainfile_invoke; - ot->exec = wm_save_as_mainfile_exec; - ot->check = blend_save_check; - /* omit window poll so this can work in background mode */ - - PropertyRNA *prop; - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE, - WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file"); - RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative", - "Make paths relative when saving to a different directory"); - - prop = RNA_def_boolean(ot->srna, "exit", false, "Exit", "Exit Blender after saving"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + ot->name = "Save Blender File"; + ot->idname = "WM_OT_save_mainfile"; + ot->description = "Save the current Blender file"; + + ot->invoke = wm_save_mainfile_invoke; + ot->exec = wm_save_as_mainfile_exec; + ot->check = blend_save_check; + /* omit window poll so this can work in background mode */ + + PropertyRNA *prop; + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, + FILE_BLENDER, + FILE_SAVE, + WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); + RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file"); + RNA_def_boolean(ot->srna, + "relative_remap", + false, + "Remap Relative", + "Make paths relative when saving to a different directory"); + + prop = RNA_def_boolean(ot->srna, "exit", false, "Exit", "Exit Blender after saving"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ @@ -2399,114 +2472,156 @@ void WM_OT_save_mainfile(wmOperatorType *ot) static void wm_block_autorun_warning_ignore(bContext *C, void *arg_block, void *UNUSED(arg)) { - wmWindow *win = CTX_wm_window(C); - UI_popup_block_close(C, win, arg_block); + wmWindow *win = CTX_wm_window(C); + UI_popup_block_close(C, win, arg_block); } static void wm_block_autorun_warning_allow(bContext *C, void *arg_block, void *UNUSED(arg)) { - PointerRNA props_ptr; - wmWindow *win = CTX_wm_window(C); + PointerRNA props_ptr; + wmWindow *win = CTX_wm_window(C); - UI_popup_block_close(C, win, arg_block); + UI_popup_block_close(C, win, arg_block); - /* Save user preferences for permanent execution. */ - if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) { - WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL); - } + /* Save user preferences for permanent execution. */ + if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) { + WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL); + } - /* Load file again with scripts enabled. */ - wmOperatorType *ot = WM_operatortype_find("WM_OT_revert_mainfile", false); + /* Load file again with scripts enabled. */ + wmOperatorType *ot = WM_operatortype_find("WM_OT_revert_mainfile", false); - WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "use_scripts", true); - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr); - WM_operator_properties_free(&props_ptr); + WM_operator_properties_create_ptr(&props_ptr, ot); + RNA_boolean_set(&props_ptr, "use_scripts", true); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); } /* Build the autorun warning dialog UI */ -static uiBlock *block_create_autorun_warning(struct bContext *C, struct ARegion *ar, void *UNUSED(arg1)) -{ - uiStyle *style = UI_style_get(); - uiBlock *block = UI_block_begin(C, ar, "autorun_warning_popup", UI_EMBOSS); - - UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); - UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); - UI_block_emboss_set(block, UI_EMBOSS); - - uiLayout *layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.widget_unit * 24, U.widget_unit * 6, 0, style); - - /* Text and some vertical space */ - uiLayout *col = uiLayoutColumn(layout, true); - uiItemL(col, IFACE_("For security reasons, automatic execution of Python scripts in this file was disabled:"), ICON_ERROR); - uiLayout *sub = uiLayoutRow(col, true); - uiLayoutSetRedAlert(sub, true); - uiItemL(sub, G.autoexec_fail, ICON_BLANK1); - uiItemL(col, IFACE_("This may lead to unexpected behavior"), ICON_BLANK1); - - uiItemS(layout); - - PointerRNA pref_ptr; - RNA_pointer_create(NULL, &RNA_PreferencesFilePaths, &U, &pref_ptr); - uiItemR(layout, &pref_ptr, "use_scripts_auto_execute", 0, IFACE_("Permanently allow execution of scripts"), ICON_NONE); - - uiItemS(layout); - - /* Buttons */ - uiBut *but; - uiLayout *split = uiLayoutSplit(layout, 0.0f, true); - col = uiLayoutColumn(split, false); - - /* Allow reload if we have a saved file. */ - if (G.relbase_valid) { - but = uiDefIconTextBut( - block, UI_BTYPE_BUT, 0, ICON_NONE, IFACE_("Allow Execution"), 0, 0, 50, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Reload file with execution of Python scripts enabled")); - UI_but_func_set(but, wm_block_autorun_warning_allow, block, NULL); - } - else { - uiItemS(col); - } - - /* empty space between buttons */ - col = uiLayoutColumn(split, false); - uiItemS(col); - - col = uiLayoutColumn(split, 1); - but = uiDefIconTextBut( - block, UI_BTYPE_BUT, 0, ICON_NONE, IFACE_("Ignore"), 0, 0, 50, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Continue using file without Python scripts")); - UI_but_func_set(but, wm_block_autorun_warning_ignore, block, NULL); - - UI_block_bounds_set_centered(block, 10); - - return block; +static uiBlock *block_create_autorun_warning(struct bContext *C, + struct ARegion *ar, + void *UNUSED(arg1)) +{ + uiStyle *style = UI_style_get(); + uiBlock *block = UI_block_begin(C, ar, "autorun_warning_popup", UI_EMBOSS); + + UI_block_flag_enable( + block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); + UI_block_emboss_set(block, UI_EMBOSS); + + uiLayout *layout = UI_block_layout(block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + 10, + 2, + U.widget_unit * 24, + U.widget_unit * 6, + 0, + style); + + /* Text and some vertical space */ + uiLayout *col = uiLayoutColumn(layout, true); + uiItemL(col, + IFACE_("For security reasons, automatic execution of Python scripts in this file was " + "disabled:"), + ICON_ERROR); + uiLayout *sub = uiLayoutRow(col, true); + uiLayoutSetRedAlert(sub, true); + uiItemL(sub, G.autoexec_fail, ICON_BLANK1); + uiItemL(col, IFACE_("This may lead to unexpected behavior"), ICON_BLANK1); + + uiItemS(layout); + + PointerRNA pref_ptr; + RNA_pointer_create(NULL, &RNA_PreferencesFilePaths, &U, &pref_ptr); + uiItemR(layout, + &pref_ptr, + "use_scripts_auto_execute", + 0, + IFACE_("Permanently allow execution of scripts"), + ICON_NONE); + + uiItemS(layout); + + /* Buttons */ + uiBut *but; + uiLayout *split = uiLayoutSplit(layout, 0.0f, true); + col = uiLayoutColumn(split, false); + + /* Allow reload if we have a saved file. */ + if (G.relbase_valid) { + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_NONE, + IFACE_("Allow Execution"), + 0, + 0, + 50, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Reload file with execution of Python scripts enabled")); + UI_but_func_set(but, wm_block_autorun_warning_allow, block, NULL); + } + else { + uiItemS(col); + } + + /* empty space between buttons */ + col = uiLayoutColumn(split, false); + uiItemS(col); + + col = uiLayoutColumn(split, 1); + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_NONE, + IFACE_("Ignore"), + 0, + 0, + 50, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Continue using file without Python scripts")); + UI_but_func_set(but, wm_block_autorun_warning_ignore, block, NULL); + + UI_block_bounds_set_centered(block, 10); + + return block; } void wm_test_autorun_warning(bContext *C) { - /* Test if any auto-execution of scripts failed. */ - if ((G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL) == 0) { - return; - } + /* Test if any auto-execution of scripts failed. */ + if ((G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL) == 0) { + return; + } - /* Only show the warning once. */ - if (G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET) { - return; - } + /* Only show the warning once. */ + if (G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET) { + return; + } - G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET; + G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET; - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = (wm->winactive) ? wm->winactive : wm->windows.first; + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = (wm->winactive) ? wm->winactive : wm->windows.first; - if (win) { - wmWindow *prevwin = CTX_wm_window(C); - CTX_wm_window_set(C, win); - UI_popup_block_invoke(C, block_create_autorun_warning, NULL); - CTX_wm_window_set(C, prevwin); - } + if (win) { + wmWindow *prevwin = CTX_wm_window(C); + CTX_wm_window_set(C, win); + UI_popup_block_invoke(C, block_create_autorun_warning, NULL); + CTX_wm_window_set(C, prevwin); + } } /** \} */ diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 56dfe4a327d..14c032e6ffa 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -70,7 +70,6 @@ #include "RNA_access.h" #include "RNA_define.h" - #include "WM_api.h" #include "WM_types.h" @@ -80,198 +79,210 @@ static bool wm_link_append_poll(bContext *C) { - if (WM_operator_winactive(C)) { - /* linking changes active object which is pretty useful in general, - * but which totally confuses edit mode (i.e. it becoming not so obvious - * to leave from edit mode and invalid tools in toolbar might be displayed) - * so disable link/append when in edit mode (sergey) */ - if (CTX_data_edit_object(C)) { - return 0; - } - - return 1; - } - - return 0; + if (WM_operator_winactive(C)) { + /* linking changes active object which is pretty useful in general, + * but which totally confuses edit mode (i.e. it becoming not so obvious + * to leave from edit mode and invalid tools in toolbar might be displayed) + * so disable link/append when in edit mode (sergey) */ + if (CTX_data_edit_object(C)) { + return 0; + } + + return 1; + } + + return 0; } static int wm_link_append_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { - if (G.lib[0] != '\0') { - RNA_string_set(op->ptr, "filepath", G.lib); - } - else if (G.relbase_valid) { - char path[FILE_MAX]; - BLI_strncpy(path, BKE_main_blendfile_path_from_global(), sizeof(path)); - BLI_parent_dir(path); - RNA_string_set(op->ptr, "filepath", path); - } - } - - WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (G.lib[0] != '\0') { + RNA_string_set(op->ptr, "filepath", G.lib); + } + else if (G.relbase_valid) { + char path[FILE_MAX]; + BLI_strncpy(path, BKE_main_blendfile_path_from_global(), sizeof(path)); + BLI_parent_dir(path); + RNA_string_set(op->ptr, "filepath", path); + } + } + + WM_event_add_fileselect(C, op); + return OPERATOR_RUNNING_MODAL; } static short wm_link_append_flag(wmOperator *op) { - PropertyRNA *prop; - short flag = 0; - - if (RNA_boolean_get(op->ptr, "autoselect")) { - flag |= FILE_AUTOSELECT; - } - if (RNA_boolean_get(op->ptr, "active_collection")) { - flag |= FILE_ACTIVE_COLLECTION; - } - if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop)) { - flag |= FILE_RELPATH; - } - if (RNA_boolean_get(op->ptr, "link")) { - flag |= FILE_LINK; - } - if (RNA_boolean_get(op->ptr, "instance_collections")) { - flag |= FILE_GROUP_INSTANCE; - } - - return flag; + PropertyRNA *prop; + short flag = 0; + + if (RNA_boolean_get(op->ptr, "autoselect")) { + flag |= FILE_AUTOSELECT; + } + if (RNA_boolean_get(op->ptr, "active_collection")) { + flag |= FILE_ACTIVE_COLLECTION; + } + if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) && + RNA_property_boolean_get(op->ptr, prop)) { + flag |= FILE_RELPATH; + } + if (RNA_boolean_get(op->ptr, "link")) { + flag |= FILE_LINK; + } + if (RNA_boolean_get(op->ptr, "instance_collections")) { + flag |= FILE_GROUP_INSTANCE; + } + + return flag; } typedef struct WMLinkAppendDataItem { - char *name; - BLI_bitmap *libraries; /* All libs (from WMLinkAppendData.libraries) to try to load this ID from. */ - short idcode; + char *name; + BLI_bitmap + *libraries; /* All libs (from WMLinkAppendData.libraries) to try to load this ID from. */ + short idcode; - ID *new_id; - void *customdata; + ID *new_id; + void *customdata; } WMLinkAppendDataItem; typedef struct WMLinkAppendData { - LinkNodePair libraries; - LinkNodePair items; - int num_libraries; - int num_items; - int flag; /* Combines eFileSel_Params_Flag from DNA_space_types.h and BLO_LibLinkFlags from BLO_readfile.h */ - - /* Internal 'private' data */ - MemArena *memarena; + LinkNodePair libraries; + LinkNodePair items; + int num_libraries; + int num_items; + int flag; /* Combines eFileSel_Params_Flag from DNA_space_types.h and BLO_LibLinkFlags from BLO_readfile.h */ + + /* Internal 'private' data */ + MemArena *memarena; } WMLinkAppendData; static WMLinkAppendData *wm_link_append_data_new(const int flag) { - MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - WMLinkAppendData *lapp_data = BLI_memarena_calloc(ma, sizeof(*lapp_data)); + MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + WMLinkAppendData *lapp_data = BLI_memarena_calloc(ma, sizeof(*lapp_data)); - lapp_data->flag = flag; - lapp_data->memarena = ma; + lapp_data->flag = flag; + lapp_data->memarena = ma; - return lapp_data; + return lapp_data; } static void wm_link_append_data_free(WMLinkAppendData *lapp_data) { - BLI_memarena_free(lapp_data->memarena); + BLI_memarena_free(lapp_data->memarena); } /* WARNING! *Never* call wm_link_append_data_library_add() after having added some items! */ static void wm_link_append_data_library_add(WMLinkAppendData *lapp_data, const char *libname) { - size_t len = strlen(libname) + 1; - char *libpath = BLI_memarena_alloc(lapp_data->memarena, len); + size_t len = strlen(libname) + 1; + char *libpath = BLI_memarena_alloc(lapp_data->memarena, len); - BLI_strncpy(libpath, libname, len); - BLI_linklist_append_arena(&lapp_data->libraries, libpath, lapp_data->memarena); - lapp_data->num_libraries++; + BLI_strncpy(libpath, libname, len); + BLI_linklist_append_arena(&lapp_data->libraries, libpath, lapp_data->memarena); + lapp_data->num_libraries++; } -static WMLinkAppendDataItem *wm_link_append_data_item_add( - WMLinkAppendData *lapp_data, const char *idname, const short idcode, void *customdata) +static WMLinkAppendDataItem *wm_link_append_data_item_add(WMLinkAppendData *lapp_data, + const char *idname, + const short idcode, + void *customdata) { - WMLinkAppendDataItem *item = BLI_memarena_alloc(lapp_data->memarena, sizeof(*item)); - size_t len = strlen(idname) + 1; + WMLinkAppendDataItem *item = BLI_memarena_alloc(lapp_data->memarena, sizeof(*item)); + size_t len = strlen(idname) + 1; - item->name = BLI_memarena_alloc(lapp_data->memarena, len); - BLI_strncpy(item->name, idname, len); - item->idcode = idcode; - item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_data->memarena, lapp_data->num_libraries); + item->name = BLI_memarena_alloc(lapp_data->memarena, len); + BLI_strncpy(item->name, idname, len); + item->idcode = idcode; + item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_data->memarena, lapp_data->num_libraries); - item->new_id = NULL; - item->customdata = customdata; + item->new_id = NULL; + item->customdata = customdata; - BLI_linklist_append_arena(&lapp_data->items, item, lapp_data->memarena); - lapp_data->num_items++; + BLI_linklist_append_arena(&lapp_data->items, item, lapp_data->memarena); + lapp_data->num_items++; - return item; + return item; } -static void wm_link_do( - WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, - Scene *scene, ViewLayer *view_layer, const View3D *v3d) +static void wm_link_do(WMLinkAppendData *lapp_data, + ReportList *reports, + Main *bmain, + Scene *scene, + ViewLayer *view_layer, + const View3D *v3d) { - Main *mainl; - BlendHandle *bh; - Library *lib; - - const int flag = lapp_data->flag; - - LinkNode *liblink, *itemlink; - int lib_idx, item_idx; - - BLI_assert(lapp_data->num_items && lapp_data->num_libraries); - - for (lib_idx = 0, liblink = lapp_data->libraries.list; liblink; lib_idx++, liblink = liblink->next) { - char *libname = liblink->link; - - if (STREQ(libname, BLO_EMBEDDED_STARTUP_BLEND)) { - bh = BLO_blendhandle_from_memory(datatoc_startup_blend, datatoc_startup_blend_size); - } - else { - bh = BLO_blendhandle_from_file(libname, reports); - } - - if (bh == NULL) { - /* Unlikely since we just browsed it, but possible - * Error reports will have been made by BLO_blendhandle_from_file() */ - continue; - } - - /* here appending/linking starts */ - mainl = BLO_library_link_begin(bmain, &bh, libname); - lib = mainl->curlib; - BLI_assert(lib); - UNUSED_VARS_NDEBUG(lib); - - if (mainl->versionfile < 250) { - BKE_reportf(reports, RPT_WARNING, - "Linking or appending from a very old .blend file format (%d.%d), no animation conversion will " - "be done! You may want to re-save your lib file with current Blender", - mainl->versionfile, mainl->subversionfile); - } - - /* For each lib file, we try to link all items belonging to that lib, - * and tag those successful to not try to load them again with the other libs. */ - for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *new_id; - - if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) { - continue; - } - - new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag); - - if (new_id) { - /* If the link is successful, clear item's libs 'todo' flags. - * This avoids trying to link same item with other libraries to come. */ - BLI_bitmap_set_all(item->libraries, false, lapp_data->num_libraries); - item->new_id = new_id; - } - } - - BLO_library_link_end(mainl, &bh, flag, bmain, scene, view_layer, v3d); - BLO_blendhandle_close(bh); - } + Main *mainl; + BlendHandle *bh; + Library *lib; + + const int flag = lapp_data->flag; + + LinkNode *liblink, *itemlink; + int lib_idx, item_idx; + + BLI_assert(lapp_data->num_items && lapp_data->num_libraries); + + for (lib_idx = 0, liblink = lapp_data->libraries.list; liblink; + lib_idx++, liblink = liblink->next) { + char *libname = liblink->link; + + if (STREQ(libname, BLO_EMBEDDED_STARTUP_BLEND)) { + bh = BLO_blendhandle_from_memory(datatoc_startup_blend, datatoc_startup_blend_size); + } + else { + bh = BLO_blendhandle_from_file(libname, reports); + } + + if (bh == NULL) { + /* Unlikely since we just browsed it, but possible + * Error reports will have been made by BLO_blendhandle_from_file() */ + continue; + } + + /* here appending/linking starts */ + mainl = BLO_library_link_begin(bmain, &bh, libname); + lib = mainl->curlib; + BLI_assert(lib); + UNUSED_VARS_NDEBUG(lib); + + if (mainl->versionfile < 250) { + BKE_reportf(reports, + RPT_WARNING, + "Linking or appending from a very old .blend file format (%d.%d), no animation " + "conversion will " + "be done! You may want to re-save your lib file with current Blender", + mainl->versionfile, + mainl->subversionfile); + } + + /* For each lib file, we try to link all items belonging to that lib, + * and tag those successful to not try to load them again with the other libs. */ + for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; + item_idx++, itemlink = itemlink->next) { + WMLinkAppendDataItem *item = itemlink->link; + ID *new_id; + + if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) { + continue; + } + + new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag); + + if (new_id) { + /* If the link is successful, clear item's libs 'todo' flags. + * This avoids trying to link same item with other libraries to come. */ + BLI_bitmap_set_all(item->libraries, false, lapp_data->num_libraries); + item->new_id = new_id; + } + } + + BLO_library_link_end(mainl, &bh, flag, bmain, scene, view_layer, v3d); + BLO_blendhandle_close(bh); + } } /** @@ -279,295 +290,327 @@ static void wm_link_do( * * \param reports: Optionally report an error when an item can't be appended/linked. */ -static bool wm_link_append_item_poll( - ReportList *reports, const char *path, const char *group, const char *name, const bool do_append) +static bool wm_link_append_item_poll(ReportList *reports, + const char *path, + const char *group, + const char *name, + const bool do_append) { - short idcode; - - if (!group || !name) { - printf("skipping %s\n", path); - return false; - } - - idcode = BKE_idcode_from_name(group); - - /* XXX For now, we do a nasty exception for workspace, forbid linking them. - * Not nice, ultimately should be solved! */ - if (!BKE_idcode_is_linkable(idcode) && (do_append || idcode != ID_WS)) { - if (reports) { - if (do_append) { - BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't append data-block '%s' of type '%s'", name, group); - } - else { - BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't link data-block '%s' of type '%s'", name, group); - } - } - return false; - } - - return true; + short idcode; + + if (!group || !name) { + printf("skipping %s\n", path); + return false; + } + + idcode = BKE_idcode_from_name(group); + + /* XXX For now, we do a nasty exception for workspace, forbid linking them. + * Not nice, ultimately should be solved! */ + if (!BKE_idcode_is_linkable(idcode) && (do_append || idcode != ID_WS)) { + if (reports) { + if (do_append) { + BKE_reportf(reports, + RPT_ERROR_INVALID_INPUT, + "Can't append data-block '%s' of type '%s'", + name, + group); + } + else { + BKE_reportf(reports, + RPT_ERROR_INVALID_INPUT, + "Can't link data-block '%s' of type '%s'", + name, + group); + } + } + return false; + } + + return true; } static int wm_link_append_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - PropertyRNA *prop; - WMLinkAppendData *lapp_data; - char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX]; - char *group, *name; - int totfiles = 0; - - RNA_string_get(op->ptr, "filename", relname); - RNA_string_get(op->ptr, "directory", root); - - BLI_join_dirfile(path, sizeof(path), root, relname); - - /* test if we have a valid data */ - if (!BLO_library_path_explode(path, libname, &group, &name)) { - BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", path); - return OPERATOR_CANCELLED; - } - else if (!group) { - BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path); - return OPERATOR_CANCELLED; - } - else if (BLI_path_cmp(BKE_main_blendfile_path(bmain), libname) == 0) { - BKE_reportf(op->reports, RPT_ERROR, "'%s': cannot use current file as library", path); - return OPERATOR_CANCELLED; - } - - /* check if something is indicated for append/link */ - prop = RNA_struct_find_property(op->ptr, "files"); - if (prop) { - totfiles = RNA_property_collection_length(op->ptr, prop); - if (totfiles == 0) { - if (!name) { - BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path); - return OPERATOR_CANCELLED; - } - } - } - else if (!name) { - BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path); - return OPERATOR_CANCELLED; - } - - short flag = wm_link_append_flag(op); - const bool do_append = (flag & FILE_LINK) == 0; - - /* sanity checks for flag */ - if (scene && scene->id.lib) { - BKE_reportf(op->reports, RPT_WARNING, - "Scene '%s' is linked, instantiation of objects & groups is disabled", scene->id.name + 2); - flag &= ~FILE_GROUP_INSTANCE; - scene = NULL; - } - - /* We need to add nothing from BLO_LibLinkFlags to flag here. */ - - /* from here down, no error returns */ - - if (view_layer && RNA_boolean_get(op->ptr, "autoselect")) { - BKE_view_layer_base_deselect_all(view_layer); - } - - /* tag everything, all untagged data can be made local - * its also generally useful to know what is new - * - * take extra care BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false) is called after! */ - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); - - /* We define our working data... - * Note that here, each item 'uses' one library, and only one. */ - lapp_data = wm_link_append_data_new(flag); - if (totfiles != 0) { - GHash *libraries = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__); - int lib_idx = 0; - - RNA_BEGIN (op->ptr, itemptr, "files") - { - RNA_string_get(&itemptr, "name", relname); - - BLI_join_dirfile(path, sizeof(path), root, relname); - - if (BLO_library_path_explode(path, libname, &group, &name)) { - if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) { - continue; - } - - if (!BLI_ghash_haskey(libraries, libname)) { - BLI_ghash_insert(libraries, BLI_strdup(libname), POINTER_FROM_INT(lib_idx)); - lib_idx++; - wm_link_append_data_library_add(lapp_data, libname); - } - } - } - RNA_END; - - RNA_BEGIN (op->ptr, itemptr, "files") - { - RNA_string_get(&itemptr, "name", relname); - - BLI_join_dirfile(path, sizeof(path), root, relname); - - if (BLO_library_path_explode(path, libname, &group, &name)) { - WMLinkAppendDataItem *item; - - if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) { - continue; - } - - lib_idx = POINTER_AS_INT(BLI_ghash_lookup(libraries, libname)); - - item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); - BLI_BITMAP_ENABLE(item->libraries, lib_idx); - } - } - RNA_END; - - BLI_ghash_free(libraries, MEM_freeN, NULL); - } - else { - WMLinkAppendDataItem *item; - - wm_link_append_data_library_add(lapp_data, libname); - item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); - BLI_BITMAP_ENABLE(item->libraries, 0); - } - - if (lapp_data->num_items == 0) { - /* Early out in case there is nothing to link. */ - wm_link_append_data_free(lapp_data); - return OPERATOR_CANCELLED; - } - - /* XXX We'd need re-entrant locking on Main for this to work... */ - /* BKE_main_lock(bmain); */ - - wm_link_do(lapp_data, op->reports, bmain, scene, view_layer, CTX_wm_view3d(C)); - - /* BKE_main_unlock(bmain); */ - - /* mark all library linked objects to be updated */ - BKE_main_lib_objects_recalc_all(bmain); - IMB_colormanagement_check_file_config(bmain); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + PropertyRNA *prop; + WMLinkAppendData *lapp_data; + char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX]; + char *group, *name; + int totfiles = 0; + + RNA_string_get(op->ptr, "filename", relname); + RNA_string_get(op->ptr, "directory", root); + + BLI_join_dirfile(path, sizeof(path), root, relname); + + /* test if we have a valid data */ + if (!BLO_library_path_explode(path, libname, &group, &name)) { + BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", path); + return OPERATOR_CANCELLED; + } + else if (!group) { + BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path); + return OPERATOR_CANCELLED; + } + else if (BLI_path_cmp(BKE_main_blendfile_path(bmain), libname) == 0) { + BKE_reportf(op->reports, RPT_ERROR, "'%s': cannot use current file as library", path); + return OPERATOR_CANCELLED; + } + + /* check if something is indicated for append/link */ + prop = RNA_struct_find_property(op->ptr, "files"); + if (prop) { + totfiles = RNA_property_collection_length(op->ptr, prop); + if (totfiles == 0) { + if (!name) { + BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path); + return OPERATOR_CANCELLED; + } + } + } + else if (!name) { + BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path); + return OPERATOR_CANCELLED; + } + + short flag = wm_link_append_flag(op); + const bool do_append = (flag & FILE_LINK) == 0; + + /* sanity checks for flag */ + if (scene && scene->id.lib) { + BKE_reportf(op->reports, + RPT_WARNING, + "Scene '%s' is linked, instantiation of objects & groups is disabled", + scene->id.name + 2); + flag &= ~FILE_GROUP_INSTANCE; + scene = NULL; + } + + /* We need to add nothing from BLO_LibLinkFlags to flag here. */ + + /* from here down, no error returns */ + + if (view_layer && RNA_boolean_get(op->ptr, "autoselect")) { + BKE_view_layer_base_deselect_all(view_layer); + } + + /* tag everything, all untagged data can be made local + * its also generally useful to know what is new + * + * take extra care BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false) is called after! */ + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); + + /* We define our working data... + * Note that here, each item 'uses' one library, and only one. */ + lapp_data = wm_link_append_data_new(flag); + if (totfiles != 0) { + GHash *libraries = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__); + int lib_idx = 0; + + RNA_BEGIN (op->ptr, itemptr, "files") { + RNA_string_get(&itemptr, "name", relname); + + BLI_join_dirfile(path, sizeof(path), root, relname); + + if (BLO_library_path_explode(path, libname, &group, &name)) { + if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) { + continue; + } + + if (!BLI_ghash_haskey(libraries, libname)) { + BLI_ghash_insert(libraries, BLI_strdup(libname), POINTER_FROM_INT(lib_idx)); + lib_idx++; + wm_link_append_data_library_add(lapp_data, libname); + } + } + } + RNA_END; + + RNA_BEGIN (op->ptr, itemptr, "files") { + RNA_string_get(&itemptr, "name", relname); + + BLI_join_dirfile(path, sizeof(path), root, relname); + + if (BLO_library_path_explode(path, libname, &group, &name)) { + WMLinkAppendDataItem *item; + + if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) { + continue; + } + + lib_idx = POINTER_AS_INT(BLI_ghash_lookup(libraries, libname)); + + item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); + BLI_BITMAP_ENABLE(item->libraries, lib_idx); + } + } + RNA_END; + + BLI_ghash_free(libraries, MEM_freeN, NULL); + } + else { + WMLinkAppendDataItem *item; + + wm_link_append_data_library_add(lapp_data, libname); + item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); + BLI_BITMAP_ENABLE(item->libraries, 0); + } + + if (lapp_data->num_items == 0) { + /* Early out in case there is nothing to link. */ + wm_link_append_data_free(lapp_data); + return OPERATOR_CANCELLED; + } + + /* XXX We'd need re-entrant locking on Main for this to work... */ + /* BKE_main_lock(bmain); */ + + wm_link_do(lapp_data, op->reports, bmain, scene, view_layer, CTX_wm_view3d(C)); + + /* BKE_main_unlock(bmain); */ + + /* mark all library linked objects to be updated */ + BKE_main_lib_objects_recalc_all(bmain); + IMB_colormanagement_check_file_config(bmain); + + /* append, rather than linking */ + if (do_append) { + const bool set_fake = RNA_boolean_get(op->ptr, "set_fake"); + const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive"); + + if (use_recursive) { + BKE_library_make_local(bmain, NULL, NULL, true, set_fake); + } + else { + LinkNode *itemlink; + GSet *done_libraries = BLI_gset_new_ex( + BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__, lapp_data->num_libraries); + + for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { + ID *new_id = ((WMLinkAppendDataItem *)(itemlink->link))->new_id; - /* append, rather than linking */ - if (do_append) { - const bool set_fake = RNA_boolean_get(op->ptr, "set_fake"); - const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive"); - - if (use_recursive) { - BKE_library_make_local(bmain, NULL, NULL, true, set_fake); - } - else { - LinkNode *itemlink; - GSet *done_libraries = BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, - __func__, lapp_data->num_libraries); + if (new_id && !BLI_gset_haskey(done_libraries, new_id->lib)) { + BKE_library_make_local(bmain, new_id->lib, NULL, true, set_fake); + BLI_gset_insert(done_libraries, new_id->lib); + } + } + + BLI_gset_free(done_libraries, NULL); + } + } - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - ID *new_id = ((WMLinkAppendDataItem *)(itemlink->link))->new_id; - - if (new_id && !BLI_gset_haskey(done_libraries, new_id->lib)) { - BKE_library_make_local(bmain, new_id->lib, NULL, true, set_fake); - BLI_gset_insert(done_libraries, new_id->lib); - } - } - - BLI_gset_free(done_libraries, NULL); - } - } - - wm_link_append_data_free(lapp_data); + wm_link_append_data_free(lapp_data); - /* important we unset, otherwise these object wont - * link into other scenes from this blend file */ - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + /* important we unset, otherwise these object wont + * link into other scenes from this blend file */ + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - /* TODO(sergey): Use proper flag for tagging here. */ + /* TODO(sergey): Use proper flag for tagging here. */ - /* TODO (dalai): Temporary solution! - * Ideally we only need to tag the new objects themselves, not the scene. This way we'll avoid flush of - * collection properties to all objects and limit update to the particular object only. - * But afraid first we need to change collection evaluation in DEG according to depsgraph manifesto. - */ - DEG_id_tag_update(&scene->id, 0); + /* TODO (dalai): Temporary solution! + * Ideally we only need to tag the new objects themselves, not the scene. This way we'll avoid flush of + * collection properties to all objects and limit update to the particular object only. + * But afraid first we need to change collection evaluation in DEG according to depsgraph manifesto. + */ + DEG_id_tag_update(&scene->id, 0); - /* recreate dependency graph to include new objects */ - DEG_relations_tag_update(bmain); + /* recreate dependency graph to include new objects */ + DEG_relations_tag_update(bmain); - /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */ - BLI_strncpy(G.lib, root, FILE_MAX); + /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */ + BLI_strncpy(G.lib, root, FILE_MAX); - WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WINDOW, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link) { - PropertyRNA *prop; - - /* better not save _any_ settings for this operator */ - /* properties */ - prop = RNA_def_boolean(ot->srna, "link", is_link, - "Link", "Link the objects or data-blocks rather than appending"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); - prop = RNA_def_boolean(ot->srna, "autoselect", true, - "Select", "Select new objects"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "active_collection", true, - "Active Collection", "Put new objects on the active collection"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "instance_collections", is_link, - "Instance Collections", "Create instances for collections, rather than adding them directly to the scene"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + /* better not save _any_ settings for this operator */ + /* properties */ + prop = RNA_def_boolean( + ot->srna, "link", is_link, "Link", "Link the objects or data-blocks rather than appending"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + prop = RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select new objects"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, + "active_collection", + true, + "Active Collection", + "Put new objects on the active collection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, + "instance_collections", + is_link, + "Instance Collections", + "Create instances for collections, rather than adding them directly to the scene"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } void WM_OT_link(wmOperatorType *ot) { - ot->name = "Link from Library"; - ot->idname = "WM_OT_link"; - ot->description = "Link from a Library .blend file"; - - ot->invoke = wm_link_append_invoke; - ot->exec = wm_link_append_exec; - ot->poll = wm_link_append_poll; - - ot->flag |= OPTYPE_UNDO; - - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, FILE_LOADLIB, FILE_OPENFILE, - WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_RELPATH | WM_FILESEL_FILES, - FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - - wm_link_append_properties_common(ot, true); + ot->name = "Link from Library"; + ot->idname = "WM_OT_link"; + ot->description = "Link from a Library .blend file"; + + ot->invoke = wm_link_append_invoke; + ot->exec = wm_link_append_exec; + ot->poll = wm_link_append_poll; + + ot->flag |= OPTYPE_UNDO; + + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, + FILE_LOADLIB, + FILE_OPENFILE, + WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | + WM_FILESEL_RELPATH | WM_FILESEL_FILES, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); + + wm_link_append_properties_common(ot, true); } void WM_OT_append(wmOperatorType *ot) { - ot->name = "Append from Library"; - ot->idname = "WM_OT_append"; - ot->description = "Append from a Library .blend file"; - - ot->invoke = wm_link_append_invoke; - ot->exec = wm_link_append_exec; - ot->poll = wm_link_append_poll; - - ot->flag |= OPTYPE_UNDO; - - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, FILE_LOADLIB, FILE_OPENFILE, - WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_FILES, - FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - - wm_link_append_properties_common(ot, false); - RNA_def_boolean(ot->srna, "set_fake", false, "Fake User", - "Set Fake User for appended items (except Objects and Groups)"); - RNA_def_boolean(ot->srna, "use_recursive", true, "Localize All", - "Localize all appended data, including those indirectly linked from other libraries"); + ot->name = "Append from Library"; + ot->idname = "WM_OT_append"; + ot->description = "Append from a Library .blend file"; + + ot->invoke = wm_link_append_invoke; + ot->exec = wm_link_append_exec; + ot->poll = wm_link_append_poll; + + ot->flag |= OPTYPE_UNDO; + + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, + FILE_LOADLIB, + FILE_OPENFILE, + WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | + WM_FILESEL_FILES, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); + + wm_link_append_properties_common(ot, false); + RNA_def_boolean(ot->srna, + "set_fake", + false, + "Fake User", + "Set Fake User for appended items (except Objects and Groups)"); + RNA_def_boolean( + ot->srna, + "use_recursive", + true, + "Localize All", + "Localize all appended data, including those indirectly linked from other libraries"); } /** \name Reload/relocate libraries. @@ -576,415 +619,443 @@ void WM_OT_append(wmOperatorType *ot) static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Library *lib; - char lib_name[MAX_NAME]; + Library *lib; + char lib_name[MAX_NAME]; - RNA_string_get(op->ptr, "library", lib_name); - lib = (Library *)BKE_libblock_find_name(CTX_data_main(C), ID_LI, lib_name); + RNA_string_get(op->ptr, "library", lib_name); + lib = (Library *)BKE_libblock_find_name(CTX_data_main(C), ID_LI, lib_name); - if (lib) { - if (lib->parent) { - BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, - "Cannot relocate indirectly linked library '%s'", lib->filepath); - return OPERATOR_CANCELLED; - } - RNA_string_set(op->ptr, "filepath", lib->filepath); + if (lib) { + if (lib->parent) { + BKE_reportf(op->reports, + RPT_ERROR_INVALID_INPUT, + "Cannot relocate indirectly linked library '%s'", + lib->filepath); + return OPERATOR_CANCELLED; + } + RNA_string_set(op->ptr, "filepath", lib->filepath); - WM_event_add_fileselect(C, op); + WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; - } + return OPERATOR_RUNNING_MODAL; + } - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } -static void lib_relocate_do( - Main *bmain, - Library *library, WMLinkAppendData *lapp_data, ReportList *reports, const bool do_reload) +static void lib_relocate_do(Main *bmain, + Library *library, + WMLinkAppendData *lapp_data, + ReportList *reports, + const bool do_reload) { - ListBase *lbarray[MAX_LIBARRAY]; - int lba_idx; + ListBase *lbarray[MAX_LIBARRAY]; + int lba_idx; - LinkNode *itemlink; - int item_idx; + LinkNode *itemlink; + int item_idx; - /* Remove all IDs to be reloaded from Main. */ - lba_idx = set_listbasepointers(bmain, lbarray); - while (lba_idx--) { - ID *id = lbarray[lba_idx]->first; - const short idcode = id ? GS(id->name) : 0; + /* Remove all IDs to be reloaded from Main. */ + lba_idx = set_listbasepointers(bmain, lbarray); + while (lba_idx--) { + ID *id = lbarray[lba_idx]->first; + const short idcode = id ? GS(id->name) : 0; - if (!id || !BKE_idcode_is_linkable(idcode)) { - /* No need to reload non-linkable datatypes, those will get relinked with their 'users ID'. */ - continue; - } + if (!id || !BKE_idcode_is_linkable(idcode)) { + /* No need to reload non-linkable datatypes, those will get relinked with their 'users ID'. */ + continue; + } - for (; id; id = id->next) { - if (id->lib == library) { - WMLinkAppendDataItem *item; + for (; id; id = id->next) { + if (id->lib == library) { + WMLinkAppendDataItem *item; - /* We remove it from current Main, and add it to items to link... */ - /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */ - BLI_remlink(lbarray[lba_idx], id); - item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id); - BLI_bitmap_set_all(item->libraries, true, lapp_data->num_libraries); + /* We remove it from current Main, and add it to items to link... */ + /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */ + BLI_remlink(lbarray[lba_idx], id); + item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id); + BLI_bitmap_set_all(item->libraries, true, lapp_data->num_libraries); #ifdef PRINT_DEBUG - printf("\tdatablock to seek for: %s\n", id->name); + printf("\tdatablock to seek for: %s\n", id->name); #endif - } - } - } - - if (lapp_data->num_items == 0) { - /* Early out in case there is nothing to do. */ - return; - } - - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); - - /* We do not want any instantiation here! */ - wm_link_do(lapp_data, reports, bmain, NULL, NULL, NULL); - - BKE_main_lock(bmain); - - /* We add back old id to bmain. - * We need to do this in a first, separated loop, otherwise some of those may not be handled by - * ID remapping, which means they would still reference old data to be deleted... */ - for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *old_id = item->customdata; - - BLI_assert(old_id); - BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id); - } - - /* Note that in reload case, we also want to replace indirect usages. */ - const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE | - (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE); - for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *old_id = item->customdata; - ID *new_id = item->new_id; - - BLI_assert(old_id); - if (do_reload) { - /* Since we asked for placeholders in case of missing IDs, we expect to always get a valid one. */ - BLI_assert(new_id); - } - if (new_id) { + } + } + } + + if (lapp_data->num_items == 0) { + /* Early out in case there is nothing to do. */ + return; + } + + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); + + /* We do not want any instantiation here! */ + wm_link_do(lapp_data, reports, bmain, NULL, NULL, NULL); + + BKE_main_lock(bmain); + + /* We add back old id to bmain. + * We need to do this in a first, separated loop, otherwise some of those may not be handled by + * ID remapping, which means they would still reference old data to be deleted... */ + for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; + item_idx++, itemlink = itemlink->next) { + WMLinkAppendDataItem *item = itemlink->link; + ID *old_id = item->customdata; + + BLI_assert(old_id); + BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id); + } + + /* Note that in reload case, we also want to replace indirect usages. */ + const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | + ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE | + (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE); + for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; + item_idx++, itemlink = itemlink->next) { + WMLinkAppendDataItem *item = itemlink->link; + ID *old_id = item->customdata; + ID *new_id = item->new_id; + + BLI_assert(old_id); + if (do_reload) { + /* Since we asked for placeholders in case of missing IDs, we expect to always get a valid one. */ + BLI_assert(new_id); + } + if (new_id) { #ifdef PRINT_DEBUG - printf("before remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us); + printf("before remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us); #endif - BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags); + BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags); - if (old_id->flag & LIB_FAKEUSER) { - id_fake_user_clear(old_id); - id_fake_user_set(new_id); - } + if (old_id->flag & LIB_FAKEUSER) { + id_fake_user_clear(old_id); + id_fake_user_set(new_id); + } #ifdef PRINT_DEBUG - printf("after remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us); + printf("after remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us); #endif - /* In some cases, new_id might become direct link, remove parent of library in this case. */ - if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) { - if (do_reload) { - BLI_assert(0); /* Should not happen in 'pure' reload case... */ - } - new_id->lib->parent = NULL; - } - } - - if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) { - /* Note that this *should* not happen - but better be safe than sorry in this area, at least until we are - * 100% sure this cannot ever happen. - * Also, we can safely assume names were unique so far, so just replacing '.' by '~' should work, - * but this does not totally rules out the possibility of name collision. */ - size_t len = strlen(old_id->name); - size_t dot_pos; - bool has_num = false; - - for (dot_pos = len; dot_pos--;) { - char c = old_id->name[dot_pos]; - if (c == '.') { - break; - } - else if (c < '0' || c > '9') { - has_num = false; - break; - } - has_num = true; - } - - if (has_num) { - old_id->name[dot_pos] = '~'; - } - else { - len = MIN2(len, MAX_ID_NAME - 7); - BLI_strncpy(&old_id->name[len], "~000", 7); - } - - id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id); - - BKE_reportf(reports, RPT_WARNING, - "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, " - "old one (%d remaining users) had to be kept and was renamed to '%s'", - new_id->name, old_id->us, old_id->name); - } - } - - BKE_main_unlock(bmain); - - for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *old_id = item->customdata; - - if (old_id->us == 0) { - BKE_id_free(bmain, old_id); - } - } - - /* Some datablocks can get reloaded/replaced 'silently' because they are not linkable (shape keys e.g.), - * so we need another loop here to clear old ones if possible. */ - lba_idx = set_listbasepointers(bmain, lbarray); - while (lba_idx--) { - ID *id, *id_next; - for (id = lbarray[lba_idx]->first; id; id = id_next) { - id_next = id->next; - /* XXX That check may be a bit to generic/permissive? */ - if (id->lib && (id->flag & LIB_TAG_PRE_EXISTING) && id->us == 0) { - BKE_id_free(bmain, id); - } - } - } - - /* Get rid of no more used libraries... */ - BKE_main_id_tag_idcode(bmain, ID_LI, LIB_TAG_DOIT, true); - lba_idx = set_listbasepointers(bmain, lbarray); - while (lba_idx--) { - ID *id; - for (id = lbarray[lba_idx]->first; id; id = id->next) { - if (id->lib) { - id->lib->id.tag &= ~LIB_TAG_DOIT; - } - } - } - Library *lib, *lib_next; - for (lib = which_libbase(bmain, ID_LI)->first; lib; lib = lib_next) { - lib_next = lib->id.next; - if (lib->id.tag & LIB_TAG_DOIT) { - id_us_clear_real(&lib->id); - if (lib->id.us == 0) { - BKE_id_free(bmain, (ID *)lib); - } - } - } - - BKE_main_lib_objects_recalc_all(bmain); - IMB_colormanagement_check_file_config(bmain); - - /* important we unset, otherwise these object wont - * link into other scenes from this blend file */ - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - - /* recreate dependency graph to include new objects */ - DEG_relations_tag_update(bmain); + /* In some cases, new_id might become direct link, remove parent of library in this case. */ + if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) { + if (do_reload) { + BLI_assert(0); /* Should not happen in 'pure' reload case... */ + } + new_id->lib->parent = NULL; + } + } + + if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) { + /* Note that this *should* not happen - but better be safe than sorry in this area, at least until we are + * 100% sure this cannot ever happen. + * Also, we can safely assume names were unique so far, so just replacing '.' by '~' should work, + * but this does not totally rules out the possibility of name collision. */ + size_t len = strlen(old_id->name); + size_t dot_pos; + bool has_num = false; + + for (dot_pos = len; dot_pos--;) { + char c = old_id->name[dot_pos]; + if (c == '.') { + break; + } + else if (c < '0' || c > '9') { + has_num = false; + break; + } + has_num = true; + } + + if (has_num) { + old_id->name[dot_pos] = '~'; + } + else { + len = MIN2(len, MAX_ID_NAME - 7); + BLI_strncpy(&old_id->name[len], "~000", 7); + } + + id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id); + + BKE_reportf( + reports, + RPT_WARNING, + "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, " + "old one (%d remaining users) had to be kept and was renamed to '%s'", + new_id->name, + old_id->us, + old_id->name); + } + } + + BKE_main_unlock(bmain); + + for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; + item_idx++, itemlink = itemlink->next) { + WMLinkAppendDataItem *item = itemlink->link; + ID *old_id = item->customdata; + + if (old_id->us == 0) { + BKE_id_free(bmain, old_id); + } + } + + /* Some datablocks can get reloaded/replaced 'silently' because they are not linkable (shape keys e.g.), + * so we need another loop here to clear old ones if possible. */ + lba_idx = set_listbasepointers(bmain, lbarray); + while (lba_idx--) { + ID *id, *id_next; + for (id = lbarray[lba_idx]->first; id; id = id_next) { + id_next = id->next; + /* XXX That check may be a bit to generic/permissive? */ + if (id->lib && (id->flag & LIB_TAG_PRE_EXISTING) && id->us == 0) { + BKE_id_free(bmain, id); + } + } + } + + /* Get rid of no more used libraries... */ + BKE_main_id_tag_idcode(bmain, ID_LI, LIB_TAG_DOIT, true); + lba_idx = set_listbasepointers(bmain, lbarray); + while (lba_idx--) { + ID *id; + for (id = lbarray[lba_idx]->first; id; id = id->next) { + if (id->lib) { + id->lib->id.tag &= ~LIB_TAG_DOIT; + } + } + } + Library *lib, *lib_next; + for (lib = which_libbase(bmain, ID_LI)->first; lib; lib = lib_next) { + lib_next = lib->id.next; + if (lib->id.tag & LIB_TAG_DOIT) { + id_us_clear_real(&lib->id); + if (lib->id.us == 0) { + BKE_id_free(bmain, (ID *)lib); + } + } + } + + BKE_main_lib_objects_recalc_all(bmain); + IMB_colormanagement_check_file_config(bmain); + + /* important we unset, otherwise these object wont + * link into other scenes from this blend file */ + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + + /* recreate dependency graph to include new objects */ + DEG_relations_tag_update(bmain); } void WM_lib_reload(Library *lib, bContext *C, ReportList *reports) { - if (!BLO_has_bfile_extension(lib->filepath)) { - BKE_reportf(reports, RPT_ERROR, "'%s' is not a valid library filepath", lib->filepath); - return; - } + if (!BLO_has_bfile_extension(lib->filepath)) { + BKE_reportf(reports, RPT_ERROR, "'%s' is not a valid library filepath", lib->filepath); + return; + } - if (!BLI_exists(lib->filepath)) { - BKE_reportf(reports, RPT_ERROR, - "Trying to reload library '%s' from invalid path '%s'", lib->id.name, lib->filepath); - return; - } + if (!BLI_exists(lib->filepath)) { + BKE_reportf(reports, + RPT_ERROR, + "Trying to reload library '%s' from invalid path '%s'", + lib->id.name, + lib->filepath); + return; + } - WMLinkAppendData *lapp_data = wm_link_append_data_new(BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT); + WMLinkAppendData *lapp_data = wm_link_append_data_new(BLO_LIBLINK_USE_PLACEHOLDERS | + BLO_LIBLINK_FORCE_INDIRECT); - wm_link_append_data_library_add(lapp_data, lib->filepath); + wm_link_append_data_library_add(lapp_data, lib->filepath); - lib_relocate_do(CTX_data_main(C), lib, lapp_data, reports, true); + lib_relocate_do(CTX_data_main(C), lib, lapp_data, reports, true); - wm_link_append_data_free(lapp_data); + wm_link_append_data_free(lapp_data); - WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WINDOW, NULL); } static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) { - Library *lib; - char lib_name[MAX_NAME]; - - RNA_string_get(op->ptr, "library", lib_name); - lib = (Library *)BKE_libblock_find_name(CTX_data_main(C), ID_LI, lib_name); - - if (lib) { - Main *bmain = CTX_data_main(C); - PropertyRNA *prop; - WMLinkAppendData *lapp_data; - - char path[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX]; - short flag = 0; - - if (RNA_boolean_get(op->ptr, "relative_path")) { - flag |= FILE_RELPATH; - } - - if (lib->parent && !do_reload) { - BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, - "Cannot relocate indirectly linked library '%s'", lib->filepath); - return OPERATOR_CANCELLED; - } - - RNA_string_get(op->ptr, "directory", root); - RNA_string_get(op->ptr, "filename", libname); - - if (!BLO_has_bfile_extension(libname)) { - BKE_report(op->reports, RPT_ERROR, "Not a library"); - return OPERATOR_CANCELLED; - } - - BLI_join_dirfile(path, sizeof(path), root, libname); - - if (!BLI_exists(path)) { - BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, - "Trying to reload or relocate library '%s' to invalid path '%s'", lib->id.name, path); - return OPERATOR_CANCELLED; - } - - if (BLI_path_cmp(lib->filepath, path) == 0) { + Library *lib; + char lib_name[MAX_NAME]; + + RNA_string_get(op->ptr, "library", lib_name); + lib = (Library *)BKE_libblock_find_name(CTX_data_main(C), ID_LI, lib_name); + + if (lib) { + Main *bmain = CTX_data_main(C); + PropertyRNA *prop; + WMLinkAppendData *lapp_data; + + char path[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX]; + short flag = 0; + + if (RNA_boolean_get(op->ptr, "relative_path")) { + flag |= FILE_RELPATH; + } + + if (lib->parent && !do_reload) { + BKE_reportf(op->reports, + RPT_ERROR_INVALID_INPUT, + "Cannot relocate indirectly linked library '%s'", + lib->filepath); + return OPERATOR_CANCELLED; + } + + RNA_string_get(op->ptr, "directory", root); + RNA_string_get(op->ptr, "filename", libname); + + if (!BLO_has_bfile_extension(libname)) { + BKE_report(op->reports, RPT_ERROR, "Not a library"); + return OPERATOR_CANCELLED; + } + + BLI_join_dirfile(path, sizeof(path), root, libname); + + if (!BLI_exists(path)) { + BKE_reportf(op->reports, + RPT_ERROR_INVALID_INPUT, + "Trying to reload or relocate library '%s' to invalid path '%s'", + lib->id.name, + path); + return OPERATOR_CANCELLED; + } + + if (BLI_path_cmp(lib->filepath, path) == 0) { #ifdef PRINT_DEBUG - printf("We are supposed to reload '%s' lib (%d)...\n", lib->filepath, lib->id.us); + printf("We are supposed to reload '%s' lib (%d)...\n", lib->filepath, lib->id.us); #endif - do_reload = true; + do_reload = true; - lapp_data = wm_link_append_data_new(flag); - wm_link_append_data_library_add(lapp_data, path); - } - else { - int totfiles = 0; + lapp_data = wm_link_append_data_new(flag); + wm_link_append_data_library_add(lapp_data, path); + } + else { + int totfiles = 0; #ifdef PRINT_DEBUG - printf("We are supposed to relocate '%s' lib to new '%s' one...\n", lib->filepath, libname); + printf("We are supposed to relocate '%s' lib to new '%s' one...\n", lib->filepath, libname); #endif - /* Check if something is indicated for relocate. */ - prop = RNA_struct_find_property(op->ptr, "files"); - if (prop) { - totfiles = RNA_property_collection_length(op->ptr, prop); - if (totfiles == 0) { - if (!libname[0]) { - BKE_report(op->reports, RPT_ERROR, "Nothing indicated"); - return OPERATOR_CANCELLED; - } - } - } + /* Check if something is indicated for relocate. */ + prop = RNA_struct_find_property(op->ptr, "files"); + if (prop) { + totfiles = RNA_property_collection_length(op->ptr, prop); + if (totfiles == 0) { + if (!libname[0]) { + BKE_report(op->reports, RPT_ERROR, "Nothing indicated"); + return OPERATOR_CANCELLED; + } + } + } - lapp_data = wm_link_append_data_new(flag); + lapp_data = wm_link_append_data_new(flag); - if (totfiles) { - RNA_BEGIN (op->ptr, itemptr, "files") - { - RNA_string_get(&itemptr, "name", relname); + if (totfiles) { + RNA_BEGIN (op->ptr, itemptr, "files") { + RNA_string_get(&itemptr, "name", relname); - BLI_join_dirfile(path, sizeof(path), root, relname); + BLI_join_dirfile(path, sizeof(path), root, relname); - if (BLI_path_cmp(path, lib->filepath) == 0 || !BLO_has_bfile_extension(relname)) { - continue; - } + if (BLI_path_cmp(path, lib->filepath) == 0 || !BLO_has_bfile_extension(relname)) { + continue; + } #ifdef PRINT_DEBUG - printf("\t candidate new lib to reload datablocks from: %s\n", path); + printf("\t candidate new lib to reload datablocks from: %s\n", path); #endif - wm_link_append_data_library_add(lapp_data, path); - } - RNA_END; - } - else { + wm_link_append_data_library_add(lapp_data, path); + } + RNA_END; + } + else { #ifdef PRINT_DEBUG - printf("\t candidate new lib to reload datablocks from: %s\n", path); + printf("\t candidate new lib to reload datablocks from: %s\n", path); #endif - wm_link_append_data_library_add(lapp_data, path); - } - } + wm_link_append_data_library_add(lapp_data, path); + } + } - if (do_reload) { - lapp_data->flag |= BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT; - } + if (do_reload) { + lapp_data->flag |= BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT; + } - lib_relocate_do(bmain, lib, lapp_data, op->reports, do_reload); + lib_relocate_do(bmain, lib, lapp_data, op->reports, do_reload); - wm_link_append_data_free(lapp_data); + wm_link_append_data_free(lapp_data); - /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */ - BLI_strncpy(G.lib, root, FILE_MAX); + /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */ + BLI_strncpy(G.lib, root, FILE_MAX); - WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WINDOW, NULL); - return OPERATOR_FINISHED; - } + return OPERATOR_FINISHED; + } - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } static int wm_lib_relocate_exec(bContext *C, wmOperator *op) { - return wm_lib_relocate_exec_do(C, op, false); + return wm_lib_relocate_exec_do(C, op, false); } void WM_OT_lib_relocate(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - ot->name = "Relocate Library"; - ot->idname = "WM_OT_lib_relocate"; - ot->description = "Relocate the given library to one or several others"; + ot->name = "Relocate Library"; + ot->idname = "WM_OT_lib_relocate"; + ot->description = "Relocate the given library to one or several others"; - ot->invoke = wm_lib_relocate_invoke; - ot->exec = wm_lib_relocate_exec; + ot->invoke = wm_lib_relocate_invoke; + ot->exec = wm_lib_relocate_exec; - ot->flag |= OPTYPE_UNDO; + ot->flag |= OPTYPE_UNDO; - prop = RNA_def_string(ot->srna, "library", NULL, MAX_NAME, "Library", "Library to relocate"); - RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_string(ot->srna, "library", NULL, MAX_NAME, "Library", "Library to relocate"); + RNA_def_property_flag(prop, PROP_HIDDEN); - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE, - WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_FILES | WM_FILESEL_RELPATH, - FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, + FILE_BLENDER, + FILE_OPENFILE, + WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | + WM_FILESEL_FILES | WM_FILESEL_RELPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); } static int wm_lib_reload_exec(bContext *C, wmOperator *op) { - return wm_lib_relocate_exec_do(C, op, true); + return wm_lib_relocate_exec_do(C, op, true); } void WM_OT_lib_reload(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - ot->name = "Reload Library"; - ot->idname = "WM_OT_lib_reload"; - ot->description = "Reload the given library"; + ot->name = "Reload Library"; + ot->idname = "WM_OT_lib_reload"; + ot->description = "Reload the given library"; - ot->exec = wm_lib_reload_exec; + ot->exec = wm_lib_reload_exec; - ot->flag |= OPTYPE_UNDO; + ot->flag |= OPTYPE_UNDO; - prop = RNA_def_string(ot->srna, "library", NULL, MAX_NAME, "Library", "Library to reload"); - RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_string(ot->srna, "library", NULL, MAX_NAME, "Library", "Library to reload"); + RNA_def_property_flag(prop, PROP_HIDDEN); - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE, - WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_RELPATH, - FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, + FILE_BLENDER, + FILE_OPENFILE, + WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | + WM_FILESEL_RELPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); } /** \} */ diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 7e95f36b2db..b264f6a570d 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -50,429 +50,457 @@ #include "BIF_glutil.h" - /* context checked on having screen, window and area */ wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type) { - wmGesture *gesture = MEM_callocN(sizeof(wmGesture), "new gesture"); - wmWindow *window = CTX_wm_window(C); - ARegion *ar = CTX_wm_region(C); - - BLI_addtail(&window->gesture, gesture); - - gesture->type = type; - gesture->event_type = event->type; - gesture->winrct = ar->winrct; - gesture->userdata_free = true; /* Free if userdata is set. */ - gesture->modal_state = GESTURE_MODAL_NOP; - - if (ELEM(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK, - WM_GESTURE_CIRCLE, WM_GESTURE_STRAIGHTLINE)) - { - rcti *rect = MEM_callocN(sizeof(rcti), "gesture rect new"); - - gesture->customdata = rect; - rect->xmin = event->x - gesture->winrct.xmin; - rect->ymin = event->y - gesture->winrct.ymin; - if (type == WM_GESTURE_CIRCLE) { - /* caller is responsible for initializing 'xmax' to radius. */ - } - else { - rect->xmax = event->x - gesture->winrct.xmin; - rect->ymax = event->y - gesture->winrct.ymin; - } - } - else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) { - short *lasso; - gesture->points_alloc = 1024; - gesture->customdata = lasso = MEM_mallocN(sizeof(short[2]) * gesture->points_alloc, "lasso points"); - lasso[0] = event->x - gesture->winrct.xmin; - lasso[1] = event->y - gesture->winrct.ymin; - gesture->points = 1; - } - - return gesture; + wmGesture *gesture = MEM_callocN(sizeof(wmGesture), "new gesture"); + wmWindow *window = CTX_wm_window(C); + ARegion *ar = CTX_wm_region(C); + + BLI_addtail(&window->gesture, gesture); + + gesture->type = type; + gesture->event_type = event->type; + gesture->winrct = ar->winrct; + gesture->userdata_free = true; /* Free if userdata is set. */ + gesture->modal_state = GESTURE_MODAL_NOP; + + if (ELEM(type, + WM_GESTURE_RECT, + WM_GESTURE_CROSS_RECT, + WM_GESTURE_TWEAK, + WM_GESTURE_CIRCLE, + WM_GESTURE_STRAIGHTLINE)) { + rcti *rect = MEM_callocN(sizeof(rcti), "gesture rect new"); + + gesture->customdata = rect; + rect->xmin = event->x - gesture->winrct.xmin; + rect->ymin = event->y - gesture->winrct.ymin; + if (type == WM_GESTURE_CIRCLE) { + /* caller is responsible for initializing 'xmax' to radius. */ + } + else { + rect->xmax = event->x - gesture->winrct.xmin; + rect->ymax = event->y - gesture->winrct.ymin; + } + } + else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) { + short *lasso; + gesture->points_alloc = 1024; + gesture->customdata = lasso = MEM_mallocN(sizeof(short[2]) * gesture->points_alloc, + "lasso points"); + lasso[0] = event->x - gesture->winrct.xmin; + lasso[1] = event->y - gesture->winrct.ymin; + gesture->points = 1; + } + + return gesture; } void WM_gesture_end(bContext *C, wmGesture *gesture) { - wmWindow *win = CTX_wm_window(C); - - if (win->tweak == gesture) { - win->tweak = NULL; - } - BLI_remlink(&win->gesture, gesture); - MEM_freeN(gesture->customdata); - if (gesture->userdata && gesture->userdata_free) { - MEM_freeN(gesture->userdata); - } - MEM_freeN(gesture); + wmWindow *win = CTX_wm_window(C); + + if (win->tweak == gesture) { + win->tweak = NULL; + } + BLI_remlink(&win->gesture, gesture); + MEM_freeN(gesture->customdata); + if (gesture->userdata && gesture->userdata_free) { + MEM_freeN(gesture->userdata); + } + MEM_freeN(gesture); } void WM_gestures_remove(bContext *C) { - wmWindow *win = CTX_wm_window(C); + wmWindow *win = CTX_wm_window(C); - while (win->gesture.first) { - WM_gesture_end(C, win->gesture.first); - } + while (win->gesture.first) { + WM_gesture_end(C, win->gesture.first); + } } bool WM_gesture_is_modal_first(const wmGesture *gesture) { - if (gesture == NULL) { - return true; - } - return (gesture->is_active_prev == false); + if (gesture == NULL) { + return true; + } + return (gesture->is_active_prev == false); } /* tweak and line gestures */ int wm_gesture_evaluate(wmGesture *gesture) { - if (gesture->type == WM_GESTURE_TWEAK) { - rcti *rect = gesture->customdata; - int dx = BLI_rcti_size_x(rect); - int dy = BLI_rcti_size_y(rect); - float tweak_threshold = U.tweak_threshold * U.dpi_fac; - if (abs(dx) + abs(dy) > tweak_threshold) { - int theta = round_fl_to_int(4.0f * atan2f((float)dy, (float)dx) / (float)M_PI); - int val = EVT_GESTURE_W; - - if (theta == 0) { - val = EVT_GESTURE_E; - } - else if (theta == 1) { - val = EVT_GESTURE_NE; - } - else if (theta == 2) { - val = EVT_GESTURE_N; - } - else if (theta == 3) { - val = EVT_GESTURE_NW; - } - else if (theta == -1) { - val = EVT_GESTURE_SE; - } - else if (theta == -2) { - val = EVT_GESTURE_S; - } - else if (theta == -3) { - val = EVT_GESTURE_SW; - } + if (gesture->type == WM_GESTURE_TWEAK) { + rcti *rect = gesture->customdata; + int dx = BLI_rcti_size_x(rect); + int dy = BLI_rcti_size_y(rect); + float tweak_threshold = U.tweak_threshold * U.dpi_fac; + if (abs(dx) + abs(dy) > tweak_threshold) { + int theta = round_fl_to_int(4.0f * atan2f((float)dy, (float)dx) / (float)M_PI); + int val = EVT_GESTURE_W; + + if (theta == 0) { + val = EVT_GESTURE_E; + } + else if (theta == 1) { + val = EVT_GESTURE_NE; + } + else if (theta == 2) { + val = EVT_GESTURE_N; + } + else if (theta == 3) { + val = EVT_GESTURE_NW; + } + else if (theta == -1) { + val = EVT_GESTURE_SE; + } + else if (theta == -2) { + val = EVT_GESTURE_S; + } + else if (theta == -3) { + val = EVT_GESTURE_SW; + } #if 0 - /* debug */ - if (val == 1) printf("tweak north\n"); - if (val == 2) printf("tweak north-east\n"); - if (val == 3) printf("tweak east\n"); - if (val == 4) printf("tweak south-east\n"); - if (val == 5) printf("tweak south\n"); - if (val == 6) printf("tweak south-west\n"); - if (val == 7) printf("tweak west\n"); - if (val == 8) printf("tweak north-west\n"); + /* debug */ + if (val == 1) printf("tweak north\n"); + if (val == 2) printf("tweak north-east\n"); + if (val == 3) printf("tweak east\n"); + if (val == 4) printf("tweak south-east\n"); + if (val == 5) printf("tweak south\n"); + if (val == 6) printf("tweak south-west\n"); + if (val == 7) printf("tweak west\n"); + if (val == 8) printf("tweak north-west\n"); #endif - return val; - } - } - return 0; + return val; + } + } + return 0; } - /* ******************* gesture draw ******************* */ static void wm_gesture_draw_line(wmGesture *gt) { - rcti *rect = (rcti *)gt->customdata; + rcti *rect = (rcti *)gt->customdata; - uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - glGetFloatv(GL_VIEWPORT, viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 2); /* "advanced" mode */ - immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); - immUniform1f("dash_width", 8.0f); + immUniform1i("colors_len", 2); /* "advanced" mode */ + immUniformArray4fv( + "colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); + immUniform1f("dash_width", 8.0f); - float xmin = (float)rect->xmin; - float ymin = (float)rect->ymin; + float xmin = (float)rect->xmin; + float ymin = (float)rect->ymin; - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(shdr_pos, xmin, ymin); - immVertex2f(shdr_pos, (float)rect->xmax, (float)rect->ymax); - immEnd(); + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(shdr_pos, xmin, ymin); + immVertex2f(shdr_pos, (float)rect->xmax, (float)rect->ymax); + immEnd(); - immUnbindProgram(); + immUnbindProgram(); } static void wm_gesture_draw_rect(wmGesture *gt) { - rcti *rect = (rcti *)gt->customdata; + rcti *rect = (rcti *)gt->customdata; - uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); + uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - GPU_blend(true); + GPU_blend(true); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4f(1.0f, 1.0f, 1.0f, 0.05f); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.05f); - immRecti(shdr_pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immRecti(shdr_pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); - immUnbindProgram(); + immUnbindProgram(); - GPU_blend(false); + GPU_blend(false); - shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - glGetFloatv(GL_VIEWPORT, viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 2); /* "advanced" mode */ - immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); - immUniform1f("dash_width", 8.0f); + immUniform1i("colors_len", 2); /* "advanced" mode */ + immUniformArray4fv( + "colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); + immUniform1f("dash_width", 8.0f); - imm_draw_box_wire_2d(shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, (float)rect->ymax); + imm_draw_box_wire_2d( + shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, (float)rect->ymax); - immUnbindProgram(); + immUnbindProgram(); - // wm_gesture_draw_line(gt); // draws a diagonal line in the lined box to test wm_gesture_draw_line + // wm_gesture_draw_line(gt); // draws a diagonal line in the lined box to test wm_gesture_draw_line } static void wm_gesture_draw_circle(wmGesture *gt) { - rcti *rect = (rcti *)gt->customdata; + rcti *rect = (rcti *)gt->customdata; - GPU_blend(true); + GPU_blend(true); - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4f(1.0f, 1.0f, 1.0f, 0.05f); - imm_draw_circle_fill_2d(shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, 40); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.05f); + imm_draw_circle_fill_2d(shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, 40); - immUnbindProgram(); + immUnbindProgram(); - GPU_blend(false); + GPU_blend(false); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - glGetFloatv(GL_VIEWPORT, viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 2); /* "advanced" mode */ - immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); - immUniform1f("dash_width", 4.0f); + immUniform1i("colors_len", 2); /* "advanced" mode */ + immUniformArray4fv( + "colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); + immUniform1f("dash_width", 4.0f); - imm_draw_circle_wire_2d(shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, 40); + imm_draw_circle_wire_2d(shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, 40); - immUnbindProgram(); + immUnbindProgram(); } struct LassoFillData { - unsigned char *px; - int width; + unsigned char *px; + int width; }; static void draw_filled_lasso_px_cb(int x, int x_end, int y, void *user_data) { - struct LassoFillData *data = user_data; - unsigned char *col = &(data->px[(y * data->width) + x]); - memset(col, 0x10, x_end - x); + struct LassoFillData *data = user_data; + unsigned char *col = &(data->px[(y * data->width) + x]); + memset(col, 0x10, x_end - x); } static void draw_filled_lasso(wmGesture *gt) { - const short *lasso = (short *)gt->customdata; - const int tot = gt->points; - int (*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__); - int i; - rcti rect; - float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - - for (i = 0; i < tot; i++, lasso += 2) { - moves[i][0] = lasso[0]; - moves[i][1] = lasso[1]; - } - - BLI_lasso_boundbox(&rect, (const int (*)[2])moves, tot); - - BLI_rcti_translate(&rect, gt->winrct.xmin, gt->winrct.ymin); - BLI_rcti_isect(>->winrct, &rect, &rect); - BLI_rcti_translate(&rect, -gt->winrct.xmin, -gt->winrct.ymin); - - /* highly unlikely this will fail, but could crash if (tot == 0) */ - if (BLI_rcti_is_empty(&rect) == false) { - const int w = BLI_rcti_size_x(&rect); - const int h = BLI_rcti_size_y(&rect); - unsigned char *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__); - struct LassoFillData lasso_fill_data = {pixel_buf, w}; - - BLI_bitmap_draw_2d_poly_v2i_n( - rect.xmin, rect.ymin, rect.xmax, rect.ymax, - (const int (*)[2])moves, tot, - draw_filled_lasso_px_cb, &lasso_fill_data); - - /* Additive Blending */ - GPU_blend(true); - glBlendFunc(GL_ONE, GL_ONE); - - GLint unpack_alignment; - glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); - GPU_shader_bind(state.shader); - GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); - - immDrawPixelsTex(&state, rect.xmin, rect.ymin, w, h, GL_RED, GL_UNSIGNED_BYTE, GL_NEAREST, pixel_buf, 1.0f, 1.0f, NULL); - - GPU_shader_unbind(); - - glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); - - MEM_freeN(pixel_buf); - - GPU_blend(false); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - MEM_freeN(moves); + const short *lasso = (short *)gt->customdata; + const int tot = gt->points; + int(*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__); + int i; + rcti rect; + float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; + + for (i = 0; i < tot; i++, lasso += 2) { + moves[i][0] = lasso[0]; + moves[i][1] = lasso[1]; + } + + BLI_lasso_boundbox(&rect, (const int(*)[2])moves, tot); + + BLI_rcti_translate(&rect, gt->winrct.xmin, gt->winrct.ymin); + BLI_rcti_isect(>->winrct, &rect, &rect); + BLI_rcti_translate(&rect, -gt->winrct.xmin, -gt->winrct.ymin); + + /* highly unlikely this will fail, but could crash if (tot == 0) */ + if (BLI_rcti_is_empty(&rect) == false) { + const int w = BLI_rcti_size_x(&rect); + const int h = BLI_rcti_size_y(&rect); + unsigned char *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__); + struct LassoFillData lasso_fill_data = {pixel_buf, w}; + + BLI_bitmap_draw_2d_poly_v2i_n(rect.xmin, + rect.ymin, + rect.xmax, + rect.ymax, + (const int(*)[2])moves, + tot, + draw_filled_lasso_px_cb, + &lasso_fill_data); + + /* Additive Blending */ + GPU_blend(true); + glBlendFunc(GL_ONE, GL_ONE); + + GLint unpack_alignment; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_bind(state.shader); + GPU_shader_uniform_vector( + state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); + + immDrawPixelsTex(&state, + rect.xmin, + rect.ymin, + w, + h, + GL_RED, + GL_UNSIGNED_BYTE, + GL_NEAREST, + pixel_buf, + 1.0f, + 1.0f, + NULL); + + GPU_shader_unbind(); + + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); + + MEM_freeN(pixel_buf); + + GPU_blend(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + MEM_freeN(moves); } - static void wm_gesture_draw_lasso(wmGesture *gt, bool filled) { - const short *lasso = (short *)gt->customdata; - int i; + const short *lasso = (short *)gt->customdata; + int i; - if (filled) { - draw_filled_lasso(gt); - } + if (filled) { + draw_filled_lasso(gt); + } - const int numverts = gt->points; + const int numverts = gt->points; - /* Nothing to draw, do early output. */ - if (numverts < 2) { - return; - } + /* Nothing to draw, do early output. */ + if (numverts < 2) { + return; + } - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - glGetFloatv(GL_VIEWPORT, viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 2); /* "advanced" mode */ - immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); - immUniform1f("dash_width", 2.0f); + immUniform1i("colors_len", 2); /* "advanced" mode */ + immUniformArray4fv( + "colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); + immUniform1f("dash_width", 2.0f); - immBegin((gt->type == WM_GESTURE_LASSO) ? GPU_PRIM_LINE_LOOP : GPU_PRIM_LINE_STRIP, numverts); + immBegin((gt->type == WM_GESTURE_LASSO) ? GPU_PRIM_LINE_LOOP : GPU_PRIM_LINE_STRIP, numverts); - for (i = 0; i < gt->points; i++, lasso += 2) { - immVertex2f(shdr_pos, (float)lasso[0], (float)lasso[1]); - } + for (i = 0; i < gt->points; i++, lasso += 2) { + immVertex2f(shdr_pos, (float)lasso[0], (float)lasso[1]); + } - immEnd(); + immEnd(); - immUnbindProgram(); + immUnbindProgram(); } static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt) { - rcti *rect = (rcti *)gt->customdata; - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); + rcti *rect = (rcti *)gt->customdata; + const int winsize_x = WM_window_pixels_x(win); + const int winsize_y = WM_window_pixels_y(win); - float x1, x2, y1, y2; + float x1, x2, y1, y2; - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - glGetFloatv(GL_VIEWPORT, viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 2); /* "advanced" mode */ - immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); - immUniform1f("dash_width", 8.0f); + immUniform1i("colors_len", 2); /* "advanced" mode */ + immUniformArray4fv( + "colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); + immUniform1f("dash_width", 8.0f); - immBegin(GPU_PRIM_LINES, 4); + immBegin(GPU_PRIM_LINES, 4); - x1 = (float)(rect->xmin - winsize_x); - y1 = (float)rect->ymin; - x2 = (float)(rect->xmin + winsize_x); - y2 = y1; + x1 = (float)(rect->xmin - winsize_x); + y1 = (float)rect->ymin; + x2 = (float)(rect->xmin + winsize_x); + y2 = y1; - immVertex2f(shdr_pos, x1, y1); - immVertex2f(shdr_pos, x2, y2); + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); - x1 = (float)rect->xmin; - y1 = (float)(rect->ymin - winsize_y); - x2 = x1; - y2 = (float)(rect->ymin + winsize_y); + x1 = (float)rect->xmin; + y1 = (float)(rect->ymin - winsize_y); + x2 = x1; + y2 = (float)(rect->ymin + winsize_y); - immVertex2f(shdr_pos, x1, y1); - immVertex2f(shdr_pos, x2, y2); + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); - immEnd(); + immEnd(); - immUnbindProgram(); + immUnbindProgram(); } /* called in wm_draw.c */ void wm_gesture_draw(wmWindow *win) { - wmGesture *gt = (wmGesture *)win->gesture.first; - - GPU_line_width(1.0f); - for (; gt; gt = gt->next) { - /* all in subwindow space */ - wmViewport(>->winrct); - - if (gt->type == WM_GESTURE_RECT) { - wm_gesture_draw_rect(gt); - } -// else if (gt->type == WM_GESTURE_TWEAK) -// wm_gesture_draw_line(gt); - else if (gt->type == WM_GESTURE_CIRCLE) { - wm_gesture_draw_circle(gt); - } - else if (gt->type == WM_GESTURE_CROSS_RECT) { - if (gt->is_active) { - wm_gesture_draw_rect(gt); - } - else { - wm_gesture_draw_cross(win, gt); - } - } - else if (gt->type == WM_GESTURE_LINES) { - wm_gesture_draw_lasso(gt, false); - } - else if (gt->type == WM_GESTURE_LASSO) { - wm_gesture_draw_lasso(gt, true); - } - else if (gt->type == WM_GESTURE_STRAIGHTLINE) { - wm_gesture_draw_line(gt); - } - } + wmGesture *gt = (wmGesture *)win->gesture.first; + + GPU_line_width(1.0f); + for (; gt; gt = gt->next) { + /* all in subwindow space */ + wmViewport(>->winrct); + + if (gt->type == WM_GESTURE_RECT) { + wm_gesture_draw_rect(gt); + } + // else if (gt->type == WM_GESTURE_TWEAK) + // wm_gesture_draw_line(gt); + else if (gt->type == WM_GESTURE_CIRCLE) { + wm_gesture_draw_circle(gt); + } + else if (gt->type == WM_GESTURE_CROSS_RECT) { + if (gt->is_active) { + wm_gesture_draw_rect(gt); + } + else { + wm_gesture_draw_cross(win, gt); + } + } + else if (gt->type == WM_GESTURE_LINES) { + wm_gesture_draw_lasso(gt, false); + } + else if (gt->type == WM_GESTURE_LASSO) { + wm_gesture_draw_lasso(gt, true); + } + else if (gt->type == WM_GESTURE_STRAIGHTLINE) { + wm_gesture_draw_line(gt); + } + } } void wm_gesture_tag_redraw(bContext *C) { - bScreen *screen = CTX_wm_screen(C); + bScreen *screen = CTX_wm_screen(C); - if (screen) { - screen->do_draw_gesture = true; - } + if (screen) { + screen->do_draw_gesture = true; + } } diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 98e17f77a17..254ced02b26 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -61,65 +61,67 @@ static void gesture_modal_end(bContext *C, wmOperator *op) { - wmGesture *gesture = op->customdata; + wmGesture *gesture = op->customdata; - WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */ - op->customdata = NULL; + WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */ + op->customdata = NULL; - ED_area_tag_redraw(CTX_wm_area(C)); + ED_area_tag_redraw(CTX_wm_area(C)); - if (RNA_struct_find_property(op->ptr, "cursor")) { - WM_cursor_modal_restore(CTX_wm_window(C)); - } + if (RNA_struct_find_property(op->ptr, "cursor")) { + WM_cursor_modal_restore(CTX_wm_window(C)); + } } static void gesture_modal_state_to_operator(wmOperator *op, int modal_state) { - PropertyRNA *prop; - - switch (modal_state) { - case GESTURE_MODAL_SELECT: - case GESTURE_MODAL_DESELECT: - if ((prop = RNA_struct_find_property(op->ptr, "deselect"))) { - RNA_property_boolean_set(op->ptr, prop, (modal_state == GESTURE_MODAL_DESELECT)); - } - if ((prop = RNA_struct_find_property(op->ptr, "mode"))) { - RNA_property_enum_set(op->ptr, prop, (modal_state == GESTURE_MODAL_DESELECT) ? SEL_OP_SUB : SEL_OP_ADD); - } - break; - case GESTURE_MODAL_IN: - case GESTURE_MODAL_OUT: - if ((prop = RNA_struct_find_property(op->ptr, "zoom_out"))) { - RNA_property_boolean_set(op->ptr, prop, (modal_state == GESTURE_MODAL_OUT)); - } - break; - } + PropertyRNA *prop; + + switch (modal_state) { + case GESTURE_MODAL_SELECT: + case GESTURE_MODAL_DESELECT: + if ((prop = RNA_struct_find_property(op->ptr, "deselect"))) { + RNA_property_boolean_set(op->ptr, prop, (modal_state == GESTURE_MODAL_DESELECT)); + } + if ((prop = RNA_struct_find_property(op->ptr, "mode"))) { + RNA_property_enum_set( + op->ptr, prop, (modal_state == GESTURE_MODAL_DESELECT) ? SEL_OP_SUB : SEL_OP_ADD); + } + break; + case GESTURE_MODAL_IN: + case GESTURE_MODAL_OUT: + if ((prop = RNA_struct_find_property(op->ptr, "zoom_out"))) { + RNA_property_boolean_set(op->ptr, prop, (modal_state == GESTURE_MODAL_OUT)); + } + break; + } } static int UNUSED_FUNCTION(gesture_modal_state_from_operator)(wmOperator *op) { - PropertyRNA *prop; - - if ((prop = RNA_struct_find_property(op->ptr, "deselect"))) { - if (RNA_property_is_set(op->ptr, prop)) { - return RNA_property_boolean_get(op->ptr, prop) ? GESTURE_MODAL_DESELECT : GESTURE_MODAL_SELECT; - } - } - if ((prop = RNA_struct_find_property(op->ptr, "mode"))) { - if (RNA_property_is_set(op->ptr, prop)) { - return RNA_property_enum_get(op->ptr, prop) == SEL_OP_SUB ? GESTURE_MODAL_DESELECT : GESTURE_MODAL_SELECT; - } - } - if ((prop = RNA_struct_find_property(op->ptr, "zoom_out"))) { - if (RNA_property_is_set(op->ptr, prop)) { - return RNA_property_boolean_get(op->ptr, prop) ? GESTURE_MODAL_OUT : GESTURE_MODAL_IN; - } - } - return GESTURE_MODAL_NOP; + PropertyRNA *prop; + + if ((prop = RNA_struct_find_property(op->ptr, "deselect"))) { + if (RNA_property_is_set(op->ptr, prop)) { + return RNA_property_boolean_get(op->ptr, prop) ? GESTURE_MODAL_DESELECT : + GESTURE_MODAL_SELECT; + } + } + if ((prop = RNA_struct_find_property(op->ptr, "mode"))) { + if (RNA_property_is_set(op->ptr, prop)) { + return RNA_property_enum_get(op->ptr, prop) == SEL_OP_SUB ? GESTURE_MODAL_DESELECT : + GESTURE_MODAL_SELECT; + } + } + if ((prop = RNA_struct_find_property(op->ptr, "zoom_out"))) { + if (RNA_property_is_set(op->ptr, prop)) { + return RNA_property_boolean_get(op->ptr, prop) ? GESTURE_MODAL_OUT : GESTURE_MODAL_IN; + } + } + return GESTURE_MODAL_NOP; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Border Gesture * @@ -133,136 +135,134 @@ static int UNUSED_FUNCTION(gesture_modal_state_from_operator)(wmOperator *op) static bool gesture_box_apply_rect(wmOperator *op) { - wmGesture *gesture = op->customdata; - rcti *rect = gesture->customdata; + wmGesture *gesture = op->customdata; + rcti *rect = gesture->customdata; - if (rect->xmin == rect->xmax || rect->ymin == rect->ymax) { - return 0; - } + if (rect->xmin == rect->xmax || rect->ymin == rect->ymax) { + return 0; + } - /* operator arguments and storage. */ - RNA_int_set(op->ptr, "xmin", min_ii(rect->xmin, rect->xmax)); - RNA_int_set(op->ptr, "ymin", min_ii(rect->ymin, rect->ymax)); - RNA_int_set(op->ptr, "xmax", max_ii(rect->xmin, rect->xmax)); - RNA_int_set(op->ptr, "ymax", max_ii(rect->ymin, rect->ymax)); + /* operator arguments and storage. */ + RNA_int_set(op->ptr, "xmin", min_ii(rect->xmin, rect->xmax)); + RNA_int_set(op->ptr, "ymin", min_ii(rect->ymin, rect->ymax)); + RNA_int_set(op->ptr, "xmax", max_ii(rect->xmin, rect->xmax)); + RNA_int_set(op->ptr, "ymax", max_ii(rect->ymin, rect->ymax)); - return 1; + return 1; } static bool gesture_box_apply(bContext *C, wmOperator *op) { - wmGesture *gesture = op->customdata; + wmGesture *gesture = op->customdata; - int retval; + int retval; - if (!gesture_box_apply_rect(op)) { - return 0; - } + if (!gesture_box_apply_rect(op)) { + return 0; + } - if (gesture->wait_for_input) { - gesture_modal_state_to_operator(op, gesture->modal_state); - } + if (gesture->wait_for_input) { + gesture_modal_state_to_operator(op, gesture->modal_state); + } - retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); + retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); - return 1; + return 1; } int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - const bool wait_for_input = !ISTWEAK(event->type) && RNA_boolean_get(op->ptr, "wait_for_input"); - if (wait_for_input) { - op->customdata = WM_gesture_new(C, event, WM_GESTURE_CROSS_RECT); - } - else { - op->customdata = WM_gesture_new(C, event, WM_GESTURE_RECT); - } + const bool wait_for_input = !ISTWEAK(event->type) && RNA_boolean_get(op->ptr, "wait_for_input"); + if (wait_for_input) { + op->customdata = WM_gesture_new(C, event, WM_GESTURE_CROSS_RECT); + } + else { + op->customdata = WM_gesture_new(C, event, WM_GESTURE_RECT); + } - { - wmGesture *gesture = op->customdata; - gesture->wait_for_input = wait_for_input; - } + { + wmGesture *gesture = op->customdata; + gesture->wait_for_input = wait_for_input; + } - /* add modal handler */ - WM_event_add_modal_handler(C, op); + /* add modal handler */ + WM_event_add_modal_handler(C, op); - wm_gesture_tag_redraw(C); + wm_gesture_tag_redraw(C); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event) { - wmGesture *gesture = op->customdata; - rcti *rect = gesture->customdata; - - if (event->type == MOUSEMOVE) { - if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) { - rect->xmin = rect->xmax = event->x - gesture->winrct.xmin; - rect->ymin = rect->ymax = event->y - gesture->winrct.ymin; - } - else { - rect->xmax = event->x - gesture->winrct.xmin; - rect->ymax = event->y - gesture->winrct.ymin; - } - gesture_box_apply_rect(op); - - wm_gesture_tag_redraw(C); - } - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case GESTURE_MODAL_BEGIN: - if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) { - gesture->is_active = true; - wm_gesture_tag_redraw(C); - } - break; - case GESTURE_MODAL_SELECT: - case GESTURE_MODAL_DESELECT: - case GESTURE_MODAL_IN: - case GESTURE_MODAL_OUT: - if (gesture->wait_for_input) { - gesture->modal_state = event->val; - } - if (gesture_box_apply(C, op)) { - gesture_modal_end(C, op); - return OPERATOR_FINISHED; - } - gesture_modal_end(C, op); - return OPERATOR_CANCELLED; - - case GESTURE_MODAL_CANCEL: - gesture_modal_end(C, op); - return OPERATOR_CANCELLED; - } - - } + wmGesture *gesture = op->customdata; + rcti *rect = gesture->customdata; + + if (event->type == MOUSEMOVE) { + if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) { + rect->xmin = rect->xmax = event->x - gesture->winrct.xmin; + rect->ymin = rect->ymax = event->y - gesture->winrct.ymin; + } + else { + rect->xmax = event->x - gesture->winrct.xmin; + rect->ymax = event->y - gesture->winrct.ymin; + } + gesture_box_apply_rect(op); + + wm_gesture_tag_redraw(C); + } + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case GESTURE_MODAL_BEGIN: + if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) { + gesture->is_active = true; + wm_gesture_tag_redraw(C); + } + break; + case GESTURE_MODAL_SELECT: + case GESTURE_MODAL_DESELECT: + case GESTURE_MODAL_IN: + case GESTURE_MODAL_OUT: + if (gesture->wait_for_input) { + gesture->modal_state = event->val; + } + if (gesture_box_apply(C, op)) { + gesture_modal_end(C, op); + return OPERATOR_FINISHED; + } + gesture_modal_end(C, op); + return OPERATOR_CANCELLED; + + case GESTURE_MODAL_CANCEL: + gesture_modal_end(C, op); + return OPERATOR_CANCELLED; + } + } #ifdef WITH_INPUT_NDOF - else if (event->type == NDOF_MOTION) { - return OPERATOR_PASS_THROUGH; - } + else if (event->type == NDOF_MOTION) { + return OPERATOR_PASS_THROUGH; + } #endif #if 0 - /* Allow view navigation??? */ - else { - return OPERATOR_PASS_THROUGH; - } + /* Allow view navigation??? */ + else { + return OPERATOR_PASS_THROUGH; + } #endif - gesture->is_active_prev = gesture->is_active; - return OPERATOR_RUNNING_MODAL; + gesture->is_active_prev = gesture->is_active; + return OPERATOR_RUNNING_MODAL; } void WM_gesture_box_cancel(bContext *C, wmOperator *op) { - gesture_modal_end(C, op); + gesture_modal_end(C, op); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Circle Gesture * @@ -275,415 +275,410 @@ static void gesture_circle_apply(bContext *C, wmOperator *op); int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - const bool wait_for_input = !ISTWEAK(event->type) && RNA_boolean_get(op->ptr, "wait_for_input"); + const bool wait_for_input = !ISTWEAK(event->type) && RNA_boolean_get(op->ptr, "wait_for_input"); - op->customdata = WM_gesture_new(C, event, WM_GESTURE_CIRCLE); - wmGesture *gesture = op->customdata; - rcti *rect = gesture->customdata; + op->customdata = WM_gesture_new(C, event, WM_GESTURE_CIRCLE); + wmGesture *gesture = op->customdata; + rcti *rect = gesture->customdata; - /* Default or previously stored value. */ - rect->xmax = RNA_int_get(op->ptr, "radius"); + /* Default or previously stored value. */ + rect->xmax = RNA_int_get(op->ptr, "radius"); - gesture->wait_for_input = wait_for_input; + gesture->wait_for_input = wait_for_input; - /* Starting with the mode starts immediately, like having 'wait_for_input' disabled (some tools use this). */ - if (gesture->wait_for_input == false) { - gesture->is_active = true; - gesture_circle_apply(C, op); - } + /* Starting with the mode starts immediately, like having 'wait_for_input' disabled (some tools use this). */ + if (gesture->wait_for_input == false) { + gesture->is_active = true; + gesture_circle_apply(C, op); + } - /* add modal handler */ - WM_event_add_modal_handler(C, op); + /* add modal handler */ + WM_event_add_modal_handler(C, op); - wm_gesture_tag_redraw(C); + wm_gesture_tag_redraw(C); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } static void gesture_circle_apply(bContext *C, wmOperator *op) { - wmGesture *gesture = op->customdata; - rcti *rect = gesture->customdata; - - if (gesture->wait_for_input && - (gesture->modal_state == GESTURE_MODAL_NOP)) - { - return; - } - - /* operator arguments and storage. */ - RNA_int_set(op->ptr, "x", rect->xmin); - RNA_int_set(op->ptr, "y", rect->ymin); - RNA_int_set(op->ptr, "radius", rect->xmax); - - /* When 'wait_for_input' is false, use properties to get the selection state. - * typically tool settings. This is done so executing as a mode can select & de-select, see: T58594. */ - if (gesture->wait_for_input) { - gesture_modal_state_to_operator(op, gesture->modal_state); - } - - if (op->type->exec) { - int retval; - retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); - } + wmGesture *gesture = op->customdata; + rcti *rect = gesture->customdata; + + if (gesture->wait_for_input && (gesture->modal_state == GESTURE_MODAL_NOP)) { + return; + } + + /* operator arguments and storage. */ + RNA_int_set(op->ptr, "x", rect->xmin); + RNA_int_set(op->ptr, "y", rect->ymin); + RNA_int_set(op->ptr, "radius", rect->xmax); + + /* When 'wait_for_input' is false, use properties to get the selection state. + * typically tool settings. This is done so executing as a mode can select & de-select, see: T58594. */ + if (gesture->wait_for_input) { + gesture_modal_state_to_operator(op, gesture->modal_state); + } + + if (op->type->exec) { + int retval; + retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + } } int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) { - wmGesture *gesture = op->customdata; - rcti *rect = gesture->customdata; - - if (event->type == MOUSEMOVE) { - - rect->xmin = event->x - gesture->winrct.xmin; - rect->ymin = event->y - gesture->winrct.ymin; - - wm_gesture_tag_redraw(C); - - if (gesture->is_active) { - gesture_circle_apply(C, op); - } - } - else if (event->type == EVT_MODAL_MAP) { - bool is_circle_size = false; - bool is_finished = false; - float fac; - - switch (event->val) { - case GESTURE_MODAL_CIRCLE_SIZE: - fac = 0.3f * (event->y - event->prevy); - if (fac > 0) { - rect->xmax += ceil(fac); - } - else { - rect->xmax += floor(fac); - } - if (rect->xmax < 1) { - rect->xmax = 1; - } - is_circle_size = true; - break; - case GESTURE_MODAL_CIRCLE_ADD: - rect->xmax += 2 + rect->xmax / 10; - is_circle_size = true; - break; - case GESTURE_MODAL_CIRCLE_SUB: - rect->xmax -= 2 + rect->xmax / 10; - if (rect->xmax < 1) { - rect->xmax = 1; - } - is_circle_size = true; - break; - case GESTURE_MODAL_SELECT: - case GESTURE_MODAL_DESELECT: - case GESTURE_MODAL_NOP: - { - if (gesture->wait_for_input) { - gesture->modal_state = event->val; - } - if (event->val == GESTURE_MODAL_NOP) { - /* Single action, click-drag & release to exit. */ - if (gesture->wait_for_input == false) { - is_finished = true; - } - } - else { - /* apply first click */ - gesture->is_active = true; - gesture_circle_apply(C, op); - wm_gesture_tag_redraw(C); - } - break; - } - case GESTURE_MODAL_CANCEL: - case GESTURE_MODAL_CONFIRM: - is_finished = true; - } - - if (is_finished) { - gesture_modal_end(C, op); - return OPERATOR_FINISHED; /* use finish or we don't get an undo */ - } - - if (is_circle_size) { - wm_gesture_tag_redraw(C); - - /* So next use remembers last seen size, even if we didn't apply it. */ - RNA_int_set(op->ptr, "radius", rect->xmax); - } - } + wmGesture *gesture = op->customdata; + rcti *rect = gesture->customdata; + + if (event->type == MOUSEMOVE) { + + rect->xmin = event->x - gesture->winrct.xmin; + rect->ymin = event->y - gesture->winrct.ymin; + + wm_gesture_tag_redraw(C); + + if (gesture->is_active) { + gesture_circle_apply(C, op); + } + } + else if (event->type == EVT_MODAL_MAP) { + bool is_circle_size = false; + bool is_finished = false; + float fac; + + switch (event->val) { + case GESTURE_MODAL_CIRCLE_SIZE: + fac = 0.3f * (event->y - event->prevy); + if (fac > 0) { + rect->xmax += ceil(fac); + } + else { + rect->xmax += floor(fac); + } + if (rect->xmax < 1) { + rect->xmax = 1; + } + is_circle_size = true; + break; + case GESTURE_MODAL_CIRCLE_ADD: + rect->xmax += 2 + rect->xmax / 10; + is_circle_size = true; + break; + case GESTURE_MODAL_CIRCLE_SUB: + rect->xmax -= 2 + rect->xmax / 10; + if (rect->xmax < 1) { + rect->xmax = 1; + } + is_circle_size = true; + break; + case GESTURE_MODAL_SELECT: + case GESTURE_MODAL_DESELECT: + case GESTURE_MODAL_NOP: { + if (gesture->wait_for_input) { + gesture->modal_state = event->val; + } + if (event->val == GESTURE_MODAL_NOP) { + /* Single action, click-drag & release to exit. */ + if (gesture->wait_for_input == false) { + is_finished = true; + } + } + else { + /* apply first click */ + gesture->is_active = true; + gesture_circle_apply(C, op); + wm_gesture_tag_redraw(C); + } + break; + } + case GESTURE_MODAL_CANCEL: + case GESTURE_MODAL_CONFIRM: + is_finished = true; + } + + if (is_finished) { + gesture_modal_end(C, op); + return OPERATOR_FINISHED; /* use finish or we don't get an undo */ + } + + if (is_circle_size) { + wm_gesture_tag_redraw(C); + + /* So next use remembers last seen size, even if we didn't apply it. */ + RNA_int_set(op->ptr, "radius", rect->xmax); + } + } #ifdef WITH_INPUT_NDOF - else if (event->type == NDOF_MOTION) { - return OPERATOR_PASS_THROUGH; - } + else if (event->type == NDOF_MOTION) { + return OPERATOR_PASS_THROUGH; + } #endif #if 0 - /* Allow view navigation??? */ - /* note, this gives issues: - * 1) other modal ops run on top (box select), - * 2) middlemouse is used now 3) tablet/trackpad? */ - else { - return OPERATOR_PASS_THROUGH; - } + /* Allow view navigation??? */ + /* note, this gives issues: + * 1) other modal ops run on top (box select), + * 2) middlemouse is used now 3) tablet/trackpad? */ + else { + return OPERATOR_PASS_THROUGH; + } #endif - gesture->is_active_prev = gesture->is_active; - return OPERATOR_RUNNING_MODAL; + gesture->is_active_prev = gesture->is_active; + return OPERATOR_RUNNING_MODAL; } void WM_gesture_circle_cancel(bContext *C, wmOperator *op) { - gesture_modal_end(C, op); + gesture_modal_end(C, op); } #if 0 /* template to copy from */ void WM_OT_circle_gesture(wmOperatorType *ot) { - ot->name = "Circle Gesture"; - ot->idname = "WM_OT_circle_gesture"; - ot->description = "Enter rotate mode with a circular gesture"; + ot->name = "Circle Gesture"; + ot->idname = "WM_OT_circle_gesture"; + ot->description = "Enter rotate mode with a circular gesture"; - ot->invoke = WM_gesture_circle_invoke; - ot->modal = WM_gesture_circle_modal; - ot->poll = WM_operator_winactive; + ot->invoke = WM_gesture_circle_invoke; + ot->modal = WM_gesture_circle_modal; + ot->poll = WM_operator_winactive; - /* properties */ - WM_operator_properties_gesture_circle(ot); + /* properties */ + WM_operator_properties_gesture_circle(ot); } #endif /** \} */ - /* -------------------------------------------------------------------- */ /** \name Tweak Gesture * \{ */ static void gesture_tweak_modal(bContext *C, const wmEvent *event) { - wmWindow *window = CTX_wm_window(C); - wmGesture *gesture = window->tweak; - rcti *rect = gesture->customdata; - int val; - - switch (event->type) { - case MOUSEMOVE: - case INBETWEEN_MOUSEMOVE: - - rect->xmax = event->x - gesture->winrct.xmin; - rect->ymax = event->y - gesture->winrct.ymin; - - if ((val = wm_gesture_evaluate(gesture))) { - wmEvent tevent; - - wm_event_init_from_window(window, &tevent); - /* We want to get coord from start of drag, not from point where it becomes a tweak event, see T40549 */ - tevent.x = rect->xmin + gesture->winrct.xmin; - tevent.y = rect->ymin + gesture->winrct.ymin; - if (gesture->event_type == LEFTMOUSE) { - tevent.type = EVT_TWEAK_L; - } - else if (gesture->event_type == RIGHTMOUSE) { - tevent.type = EVT_TWEAK_R; - } - else { - tevent.type = EVT_TWEAK_M; - } - tevent.val = val; - /* mouse coords! */ - - /* important we add immediately after this event, so future mouse releases - * (which may be in the queue already), are handled in order, see T44740 */ - wm_event_add_ex(window, &tevent, event); - - WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */ - } - - break; - - case LEFTMOUSE: - case RIGHTMOUSE: - case MIDDLEMOUSE: - if (gesture->event_type == event->type) { - WM_gesture_end(C, gesture); - - /* when tweak fails we should give the other keymap entries a chance */ - - /* XXX, assigning to readonly, BAD JUJU! */ - ((wmEvent *)event)->val = KM_RELEASE; - } - break; - default: - if (!ISTIMER(event->type) && event->type != EVENT_NONE) { - WM_gesture_end(C, gesture); - } - break; - } + wmWindow *window = CTX_wm_window(C); + wmGesture *gesture = window->tweak; + rcti *rect = gesture->customdata; + int val; + + switch (event->type) { + case MOUSEMOVE: + case INBETWEEN_MOUSEMOVE: + + rect->xmax = event->x - gesture->winrct.xmin; + rect->ymax = event->y - gesture->winrct.ymin; + + if ((val = wm_gesture_evaluate(gesture))) { + wmEvent tevent; + + wm_event_init_from_window(window, &tevent); + /* We want to get coord from start of drag, not from point where it becomes a tweak event, see T40549 */ + tevent.x = rect->xmin + gesture->winrct.xmin; + tevent.y = rect->ymin + gesture->winrct.ymin; + if (gesture->event_type == LEFTMOUSE) { + tevent.type = EVT_TWEAK_L; + } + else if (gesture->event_type == RIGHTMOUSE) { + tevent.type = EVT_TWEAK_R; + } + else { + tevent.type = EVT_TWEAK_M; + } + tevent.val = val; + /* mouse coords! */ + + /* important we add immediately after this event, so future mouse releases + * (which may be in the queue already), are handled in order, see T44740 */ + wm_event_add_ex(window, &tevent, event); + + WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */ + } + + break; + + case LEFTMOUSE: + case RIGHTMOUSE: + case MIDDLEMOUSE: + if (gesture->event_type == event->type) { + WM_gesture_end(C, gesture); + + /* when tweak fails we should give the other keymap entries a chance */ + + /* XXX, assigning to readonly, BAD JUJU! */ + ((wmEvent *)event)->val = KM_RELEASE; + } + break; + default: + if (!ISTIMER(event->type) && event->type != EVENT_NONE) { + WM_gesture_end(C, gesture); + } + break; + } } /* standard tweak, called after window handlers passed on event */ void wm_tweakevent_test(bContext *C, const wmEvent *event, int action) { - wmWindow *win = CTX_wm_window(C); - - if (win->tweak == NULL) { - if (CTX_wm_region(C)) { - if (event->val == KM_PRESS) { - if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) { - win->tweak = WM_gesture_new(C, event, WM_GESTURE_TWEAK); - } - } - } - } - else { - /* no tweaks if event was handled */ - if ((action & WM_HANDLER_BREAK)) { - WM_gesture_end(C, win->tweak); - } - else { - gesture_tweak_modal(C, event); - } - } + wmWindow *win = CTX_wm_window(C); + + if (win->tweak == NULL) { + if (CTX_wm_region(C)) { + if (event->val == KM_PRESS) { + if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) { + win->tweak = WM_gesture_new(C, event, WM_GESTURE_TWEAK); + } + } + } + } + else { + /* no tweaks if event was handled */ + if ((action & WM_HANDLER_BREAK)) { + WM_gesture_end(C, win->tweak); + } + else { + gesture_tweak_modal(C, event); + } + } } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Lasso Gesture * \{ */ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - PropertyRNA *prop; + PropertyRNA *prop; - op->customdata = WM_gesture_new(C, event, WM_GESTURE_LASSO); + op->customdata = WM_gesture_new(C, event, WM_GESTURE_LASSO); - /* add modal handler */ - WM_event_add_modal_handler(C, op); + /* add modal handler */ + WM_event_add_modal_handler(C, op); - wm_gesture_tag_redraw(C); + wm_gesture_tag_redraw(C); - if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) { - WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop)); - } + if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) { + WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop)); + } - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - PropertyRNA *prop; + PropertyRNA *prop; - op->customdata = WM_gesture_new(C, event, WM_GESTURE_LINES); + op->customdata = WM_gesture_new(C, event, WM_GESTURE_LINES); - /* add modal handler */ - WM_event_add_modal_handler(C, op); + /* add modal handler */ + WM_event_add_modal_handler(C, op); - wm_gesture_tag_redraw(C); + wm_gesture_tag_redraw(C); - if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) { - WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop)); - } + if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) { + WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop)); + } - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } - static void gesture_lasso_apply(bContext *C, wmOperator *op) { - wmGesture *gesture = op->customdata; - PointerRNA itemptr; - float loc[2]; - int i; - const short *lasso = gesture->customdata; - - /* operator storage as path. */ - - RNA_collection_clear(op->ptr, "path"); - for (i = 0; i < gesture->points; i++, lasso += 2) { - loc[0] = lasso[0]; - loc[1] = lasso[1]; - RNA_collection_add(op->ptr, "path", &itemptr); - RNA_float_set_array(&itemptr, "loc", loc); - } - - gesture_modal_end(C, op); - - if (op->type->exec) { - int retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); - } + wmGesture *gesture = op->customdata; + PointerRNA itemptr; + float loc[2]; + int i; + const short *lasso = gesture->customdata; + + /* operator storage as path. */ + + RNA_collection_clear(op->ptr, "path"); + for (i = 0; i < gesture->points; i++, lasso += 2) { + loc[0] = lasso[0]; + loc[1] = lasso[1]; + RNA_collection_add(op->ptr, "path", &itemptr); + RNA_float_set_array(&itemptr, "loc", loc); + } + + gesture_modal_end(C, op); + + if (op->type->exec) { + int retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + } } int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) { - wmGesture *gesture = op->customdata; - - switch (event->type) { - case MOUSEMOVE: - case INBETWEEN_MOUSEMOVE: - - wm_gesture_tag_redraw(C); - - if (gesture->points == gesture->points_alloc) { - gesture->points_alloc *= 2; - gesture->customdata = MEM_reallocN(gesture->customdata, sizeof(short[2]) * gesture->points_alloc); - } - - { - int x, y; - short *lasso = gesture->customdata; - - lasso += (2 * gesture->points - 2); - x = (event->x - gesture->winrct.xmin - lasso[0]); - y = (event->y - gesture->winrct.ymin - lasso[1]); - - /* make a simple distance check to get a smoother lasso - * add only when at least 2 pixels between this and previous location */ - if ((x * x + y * y) > 4) { - lasso += 2; - lasso[0] = event->x - gesture->winrct.xmin; - lasso[1] = event->y - gesture->winrct.ymin; - gesture->points++; - } - } - break; - - case LEFTMOUSE: - case MIDDLEMOUSE: - case RIGHTMOUSE: - if (event->val == KM_RELEASE) { /* key release */ - gesture_lasso_apply(C, op); - return OPERATOR_FINISHED; - } - break; - case ESCKEY: - gesture_modal_end(C, op); - return OPERATOR_CANCELLED; - } - - gesture->is_active_prev = gesture->is_active; - return OPERATOR_RUNNING_MODAL; + wmGesture *gesture = op->customdata; + + switch (event->type) { + case MOUSEMOVE: + case INBETWEEN_MOUSEMOVE: + + wm_gesture_tag_redraw(C); + + if (gesture->points == gesture->points_alloc) { + gesture->points_alloc *= 2; + gesture->customdata = MEM_reallocN(gesture->customdata, + sizeof(short[2]) * gesture->points_alloc); + } + + { + int x, y; + short *lasso = gesture->customdata; + + lasso += (2 * gesture->points - 2); + x = (event->x - gesture->winrct.xmin - lasso[0]); + y = (event->y - gesture->winrct.ymin - lasso[1]); + + /* make a simple distance check to get a smoother lasso + * add only when at least 2 pixels between this and previous location */ + if ((x * x + y * y) > 4) { + lasso += 2; + lasso[0] = event->x - gesture->winrct.xmin; + lasso[1] = event->y - gesture->winrct.ymin; + gesture->points++; + } + } + break; + + case LEFTMOUSE: + case MIDDLEMOUSE: + case RIGHTMOUSE: + if (event->val == KM_RELEASE) { /* key release */ + gesture_lasso_apply(C, op); + return OPERATOR_FINISHED; + } + break; + case ESCKEY: + gesture_modal_end(C, op); + return OPERATOR_CANCELLED; + } + + gesture->is_active_prev = gesture->is_active; + return OPERATOR_RUNNING_MODAL; } int WM_gesture_lines_modal(bContext *C, wmOperator *op, const wmEvent *event) { - return WM_gesture_lasso_modal(C, op, event); + return WM_gesture_lasso_modal(C, op, event); } void WM_gesture_lasso_cancel(bContext *C, wmOperator *op) { - gesture_modal_end(C, op); + gesture_modal_end(C, op); } void WM_gesture_lines_cancel(bContext *C, wmOperator *op) { - gesture_modal_end(C, op); + gesture_modal_end(C, op); } /** @@ -691,38 +686,39 @@ void WM_gesture_lines_cancel(bContext *C, wmOperator *op) * * caller must free. */ -const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *mcords_tot))[2] +const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), + wmOperator *op, + int *mcords_tot))[2] { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "path"); - int (*mcords)[2] = NULL; - BLI_assert(prop != NULL); - - if (prop) { - const int len = RNA_property_collection_length(op->ptr, prop); - - if (len) { - int i = 0; - mcords = MEM_mallocN(sizeof(int) * 2 * len, __func__); - - RNA_PROP_BEGIN (op->ptr, itemptr, prop) - { - float loc[2]; - - RNA_float_get_array(&itemptr, "loc", loc); - mcords[i][0] = (int)loc[0]; - mcords[i][1] = (int)loc[1]; - i++; - } - RNA_PROP_END; - } - *mcords_tot = len; - } - else { - *mcords_tot = 0; - } - - /* cast for 'const' */ - return (const int (*)[2])mcords; + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "path"); + int(*mcords)[2] = NULL; + BLI_assert(prop != NULL); + + if (prop) { + const int len = RNA_property_collection_length(op->ptr, prop); + + if (len) { + int i = 0; + mcords = MEM_mallocN(sizeof(int) * 2 * len, __func__); + + RNA_PROP_BEGIN (op->ptr, itemptr, prop) { + float loc[2]; + + RNA_float_get_array(&itemptr, "loc", loc); + mcords[i][0] = (int)loc[0]; + mcords[i][1] = (int)loc[1]; + i++; + } + RNA_PROP_END; + } + *mcords_tot = len; + } + else { + *mcords_tot = 0; + } + + /* cast for 'const' */ + return (const int(*)[2])mcords; } #if 0 @@ -730,157 +726,155 @@ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, static int gesture_lasso_exec(bContext *C, wmOperator *op) { - RNA_BEGIN (op->ptr, itemptr, "path") - { - float loc[2]; + RNA_BEGIN (op->ptr, itemptr, "path") + { + float loc[2]; - RNA_float_get_array(&itemptr, "loc", loc); - printf("Location: %f %f\n", loc[0], loc[1]); - } - RNA_END; + RNA_float_get_array(&itemptr, "loc", loc); + printf("Location: %f %f\n", loc[0], loc[1]); + } + RNA_END; - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void WM_OT_lasso_gesture(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - ot->name = "Lasso Gesture"; - ot->idname = "WM_OT_lasso_gesture"; - ot->description = "Select objects within the lasso as you move the pointer"; + ot->name = "Lasso Gesture"; + ot->idname = "WM_OT_lasso_gesture"; + ot->description = "Select objects within the lasso as you move the pointer"; - ot->invoke = WM_gesture_lasso_invoke; - ot->modal = WM_gesture_lasso_modal; - ot->exec = gesture_lasso_exec; + ot->invoke = WM_gesture_lasso_invoke; + ot->modal = WM_gesture_lasso_modal; + ot->exec = gesture_lasso_exec; - ot->poll = WM_operator_winactive; + ot->poll = WM_operator_winactive; - prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE); - RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath); + prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath); } #endif - /** \} */ - /* -------------------------------------------------------------------- */ /** \name Straight Line Gesture * \{ */ static bool gesture_straightline_apply(bContext *C, wmOperator *op) { - wmGesture *gesture = op->customdata; - rcti *rect = gesture->customdata; + wmGesture *gesture = op->customdata; + rcti *rect = gesture->customdata; - if (rect->xmin == rect->xmax && rect->ymin == rect->ymax) { - return 0; - } + if (rect->xmin == rect->xmax && rect->ymin == rect->ymax) { + return 0; + } - /* operator arguments and storage. */ - RNA_int_set(op->ptr, "xstart", rect->xmin); - RNA_int_set(op->ptr, "ystart", rect->ymin); - RNA_int_set(op->ptr, "xend", rect->xmax); - RNA_int_set(op->ptr, "yend", rect->ymax); + /* operator arguments and storage. */ + RNA_int_set(op->ptr, "xstart", rect->xmin); + RNA_int_set(op->ptr, "ystart", rect->ymin); + RNA_int_set(op->ptr, "xend", rect->xmax); + RNA_int_set(op->ptr, "yend", rect->ymax); - if (op->type->exec) { - int retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); - } + if (op->type->exec) { + int retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + } - return 1; + return 1; } int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - PropertyRNA *prop; + PropertyRNA *prop; - op->customdata = WM_gesture_new(C, event, WM_GESTURE_STRAIGHTLINE); + op->customdata = WM_gesture_new(C, event, WM_GESTURE_STRAIGHTLINE); - if (ISTWEAK(event->type)) { - wmGesture *gesture = op->customdata; - gesture->is_active = true; - } + if (ISTWEAK(event->type)) { + wmGesture *gesture = op->customdata; + gesture->is_active = true; + } - /* add modal handler */ - WM_event_add_modal_handler(C, op); + /* add modal handler */ + WM_event_add_modal_handler(C, op); - wm_gesture_tag_redraw(C); + wm_gesture_tag_redraw(C); - if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) { - WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop)); - } + if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) { + WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop)); + } - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event) { - wmGesture *gesture = op->customdata; - rcti *rect = gesture->customdata; - - if (event->type == MOUSEMOVE) { - if (gesture->is_active == false) { - rect->xmin = rect->xmax = event->x - gesture->winrct.xmin; - rect->ymin = rect->ymax = event->y - gesture->winrct.ymin; - } - else { - rect->xmax = event->x - gesture->winrct.xmin; - rect->ymax = event->y - gesture->winrct.ymin; - gesture_straightline_apply(C, op); - } - - wm_gesture_tag_redraw(C); - } - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case GESTURE_MODAL_BEGIN: - if (gesture->is_active == false) { - gesture->is_active = true; - wm_gesture_tag_redraw(C); - } - break; - case GESTURE_MODAL_SELECT: - if (gesture_straightline_apply(C, op)) { - gesture_modal_end(C, op); - return OPERATOR_FINISHED; - } - gesture_modal_end(C, op); - return OPERATOR_CANCELLED; - - case GESTURE_MODAL_CANCEL: - gesture_modal_end(C, op); - return OPERATOR_CANCELLED; - } - } - - gesture->is_active_prev = gesture->is_active; - return OPERATOR_RUNNING_MODAL; + wmGesture *gesture = op->customdata; + rcti *rect = gesture->customdata; + + if (event->type == MOUSEMOVE) { + if (gesture->is_active == false) { + rect->xmin = rect->xmax = event->x - gesture->winrct.xmin; + rect->ymin = rect->ymax = event->y - gesture->winrct.ymin; + } + else { + rect->xmax = event->x - gesture->winrct.xmin; + rect->ymax = event->y - gesture->winrct.ymin; + gesture_straightline_apply(C, op); + } + + wm_gesture_tag_redraw(C); + } + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case GESTURE_MODAL_BEGIN: + if (gesture->is_active == false) { + gesture->is_active = true; + wm_gesture_tag_redraw(C); + } + break; + case GESTURE_MODAL_SELECT: + if (gesture_straightline_apply(C, op)) { + gesture_modal_end(C, op); + return OPERATOR_FINISHED; + } + gesture_modal_end(C, op); + return OPERATOR_CANCELLED; + + case GESTURE_MODAL_CANCEL: + gesture_modal_end(C, op); + return OPERATOR_CANCELLED; + } + } + + gesture->is_active_prev = gesture->is_active; + return OPERATOR_RUNNING_MODAL; } void WM_gesture_straightline_cancel(bContext *C, wmOperator *op) { - gesture_modal_end(C, op); + gesture_modal_end(C, op); } #if 0 /* template to copy from */ void WM_OT_straightline_gesture(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - ot->name = "Straight Line Gesture"; - ot->idname = "WM_OT_straightline_gesture"; - ot->description = "Draw a straight line as you move the pointer"; + ot->name = "Straight Line Gesture"; + ot->idname = "WM_OT_straightline_gesture"; + ot->description = "Draw a straight line as you move the pointer"; - ot->invoke = WM_gesture_straightline_invoke; - ot->modal = WM_gesture_straightline_modal; - ot->exec = gesture_straightline_exec; + ot->invoke = WM_gesture_straightline_invoke; + ot->modal = WM_gesture_straightline_modal; + ot->exec = gesture_straightline_exec; - ot->poll = WM_operator_winactive; + ot->poll = WM_operator_winactive; - WM_operator_properties_gesture_straightline(ot, 0); + WM_operator_properties_gesture_straightline(ot, 0); } #endif diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index f39cb7d7cb2..ad3cc50ea13 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -72,13 +72,13 @@ #include "BKE_studiolight.h" #include "BKE_material.h" /* clear_matcopybuf */ #include "BKE_tracking.h" /* free tracking clipboard */ -#include "BKE_mask.h" /* free mask clipboard */ +#include "BKE_mask.h" /* free mask clipboard */ #include "RE_engine.h" -#include "RE_pipeline.h" /* RE_ free stuff */ +#include "RE_pipeline.h" /* RE_ free stuff */ #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif #include "GHOST_Path-api.h" @@ -139,24 +139,24 @@ CLG_LOGREF_DECLARE_GLOBAL(WM_LOG_MSGBUS_SUB, "wm.msgbus.sub"); static void wm_init_reports(bContext *C) { - ReportList *reports = CTX_wm_reports(C); + ReportList *reports = CTX_wm_reports(C); - BLI_assert(!reports || BLI_listbase_is_empty(&reports->list)); + BLI_assert(!reports || BLI_listbase_is_empty(&reports->list)); - BKE_reports_init(reports, RPT_STORE); + BKE_reports_init(reports, RPT_STORE); } static void wm_free_reports(bContext *C) { - ReportList *reports = CTX_wm_reports(C); + ReportList *reports = CTX_wm_reports(C); - BKE_reports_clear(reports); + BKE_reports_clear(reports); } static bool wm_start_with_console = false; void WM_init_state_start_with_console_set(bool value) { - wm_start_with_console = value; + wm_start_with_console = value; } /** @@ -170,236 +170,241 @@ static bool opengl_is_init = false; void WM_init_opengl(Main *bmain) { - /* must be called only once */ - BLI_assert(opengl_is_init == false); + /* must be called only once */ + BLI_assert(opengl_is_init == false); - if (G.background) { - /* Ghost is still not init elsewhere in background mode. */ - wm_ghost_init(NULL); - } + if (G.background) { + /* Ghost is still not init elsewhere in background mode. */ + wm_ghost_init(NULL); + } - /* Needs to be first to have an ogl context bound. */ - DRW_opengl_context_create(); + /* Needs to be first to have an ogl context bound. */ + DRW_opengl_context_create(); - GPU_init(); - GPU_set_mipmap(bmain, true); - GPU_set_linear_mipmap(true); - GPU_set_anisotropic(bmain, U.anisotropic_filter); + GPU_init(); + GPU_set_mipmap(bmain, true); + GPU_set_linear_mipmap(true); + GPU_set_anisotropic(bmain, U.anisotropic_filter); - GPU_pass_cache_init(); + GPU_pass_cache_init(); #ifdef WITH_OPENSUBDIV - BKE_subsurf_osd_init(); + BKE_subsurf_osd_init(); #endif - opengl_is_init = true; + opengl_is_init = true; } /* only called once, for startup */ void WM_init(bContext *C, int argc, const char **argv) { - if (!G.background) { - wm_ghost_init(C); /* note: it assigns C to ghost! */ - wm_init_cursor_data(); - } + if (!G.background) { + wm_ghost_init(C); /* note: it assigns C to ghost! */ + wm_init_cursor_data(); + } - GHOST_CreateSystemPaths(); + GHOST_CreateSystemPaths(); - BKE_addon_pref_type_init(); - BKE_keyconfig_pref_type_init(); + BKE_addon_pref_type_init(); + BKE_keyconfig_pref_type_init(); - wm_operatortype_init(); - wm_operatortypes_register(); + wm_operatortype_init(); + wm_operatortypes_register(); - WM_paneltype_init(); /* Lookup table only. */ - WM_menutype_init(); - WM_uilisttype_init(); - wm_gizmotype_init(); - wm_gizmogrouptype_init(); + WM_paneltype_init(); /* Lookup table only. */ + WM_menutype_init(); + WM_uilisttype_init(); + wm_gizmotype_init(); + wm_gizmogrouptype_init(); - ED_undosys_type_init(); + ED_undosys_type_init(); - BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */ - BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */ - BKE_region_callback_free_gizmomap_set(wm_gizmomap_remove); /* screen.c */ - BKE_region_callback_refresh_tag_gizmomap_set(WM_gizmomap_tag_refresh); - BKE_library_callback_remap_editor_id_reference_set(WM_main_remap_editor_id_reference); /* library.c */ - BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap); /* screen.c */ - DEG_editors_set_update_cb(ED_render_id_flush_update, - ED_render_scene_update); + BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */ + BKE_library_callback_free_notifier_reference_set( + WM_main_remove_notifier_reference); /* library.c */ + BKE_region_callback_free_gizmomap_set(wm_gizmomap_remove); /* screen.c */ + BKE_region_callback_refresh_tag_gizmomap_set(WM_gizmomap_tag_refresh); + BKE_library_callback_remap_editor_id_reference_set( + WM_main_remap_editor_id_reference); /* library.c */ + BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap); /* screen.c */ + DEG_editors_set_update_cb(ED_render_id_flush_update, ED_render_scene_update); - ED_spacetypes_init(); /* editors/space_api/spacetype.c */ + ED_spacetypes_init(); /* editors/space_api/spacetype.c */ - ED_file_init(); /* for fsmenu */ - ED_node_init_butfuncs(); + ED_file_init(); /* for fsmenu */ + ED_node_init_butfuncs(); - BLF_init(); + BLF_init(); - BLT_lang_init(); - /* Must call first before doing any .blend file reading, since versionning code may create new IDs... See T57066. */ - BLT_lang_set(NULL); + BLT_lang_init(); + /* Must call first before doing any .blend file reading, since versionning code may create new IDs... See T57066. */ + BLT_lang_set(NULL); - /* Init icons before reading .blend files for preview icons, which can - * get triggered by the depsgraph. This is also done in background mode - * for scripts that do background processing with preview icons. */ - BKE_icons_init(BIFICONID_LAST); + /* Init icons before reading .blend files for preview icons, which can + * get triggered by the depsgraph. This is also done in background mode + * for scripts that do background processing with preview icons. */ + BKE_icons_init(BIFICONID_LAST); - /* reports cant be initialized before the wm, - * but keep before file reading, since that may report errors */ - wm_init_reports(C); + /* reports cant be initialized before the wm, + * but keep before file reading, since that may report errors */ + wm_init_reports(C); - WM_msgbus_types_init(); + WM_msgbus_types_init(); - /* get the default database, plus a wm */ - bool is_factory_startup = true; - wm_homefile_read( - C, NULL, G.factory_startup, false, true, NULL, WM_init_state_app_template_get(), - &is_factory_startup); + /* get the default database, plus a wm */ + bool is_factory_startup = true; + wm_homefile_read(C, + NULL, + G.factory_startup, + false, + true, + NULL, + WM_init_state_app_template_get(), + &is_factory_startup); - /* Call again to set from userpreferences... */ - BLT_lang_set(NULL); + /* Call again to set from userpreferences... */ + BLT_lang_set(NULL); - if (!G.background) { + if (!G.background) { #ifdef WITH_INPUT_NDOF - /* sets 3D mouse deadzone */ - WM_ndof_deadzone_set(U.ndof_deadzone); + /* sets 3D mouse deadzone */ + WM_ndof_deadzone_set(U.ndof_deadzone); #endif - WM_init_opengl(G_MAIN); + WM_init_opengl(G_MAIN); - UI_init(); - } + UI_init(); + } - BKE_studiolight_init(); + BKE_studiolight_init(); - ED_spacemacros_init(); + ED_spacemacros_init(); - /* note: there is a bug where python needs initializing before loading the - * startup.blend because it may contain PyDrivers. It also needs to be after - * initializing space types and other internal data. - * - * However cant redo this at the moment. Solution is to load python - * before wm_homefile_read() or make py-drivers check if python is running. - * Will try fix when the crash can be repeated. - campbell. */ + /* note: there is a bug where python needs initializing before loading the + * startup.blend because it may contain PyDrivers. It also needs to be after + * initializing space types and other internal data. + * + * However cant redo this at the moment. Solution is to load python + * before wm_homefile_read() or make py-drivers check if python is running. + * Will try fix when the crash can be repeated. - campbell. */ #ifdef WITH_PYTHON - BPY_context_set(C); /* necessary evil */ - BPY_python_start(argc, argv); + BPY_context_set(C); /* necessary evil */ + BPY_python_start(argc, argv); - BPY_python_reset(C); + BPY_python_reset(C); #else - (void)argc; /* unused */ - (void)argv; /* unused */ + (void)argc; /* unused */ + (void)argv; /* unused */ #endif - if (!G.background && !wm_start_with_console) { - GHOST_toggleConsole(3); - } + if (!G.background && !wm_start_with_console) { + GHOST_toggleConsole(3); + } - clear_matcopybuf(); - ED_render_clear_mtex_copybuf(); + clear_matcopybuf(); + ED_render_clear_mtex_copybuf(); - // glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + // glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - wm_history_file_read(); + wm_history_file_read(); - /* allow a path of "", this is what happens when making a new file */ + /* allow a path of "", this is what happens when making a new file */ #if 0 - if (BKE_main_blendfile_path_from_global()[0] == '\0') - BLI_make_file_string("/", G_MAIN->name, BKE_appdir_folder_default(), "untitled.blend"); + if (BKE_main_blendfile_path_from_global()[0] == '\0') + BLI_make_file_string("/", G_MAIN->name, BKE_appdir_folder_default(), "untitled.blend"); #endif - BLI_strncpy(G.lib, BKE_main_blendfile_path_from_global(), sizeof(G.lib)); + BLI_strncpy(G.lib, BKE_main_blendfile_path_from_global(), sizeof(G.lib)); #ifdef WITH_COMPOSITOR - if (1) { - extern void *COM_linker_hack; - COM_linker_hack = COM_execute; - } + if (1) { + extern void *COM_linker_hack; + COM_linker_hack = COM_execute; + } #endif - { - Main *bmain = CTX_data_main(C); - /* note, logic here is from wm_file_read_post, - * call functions that depend on Python being initialized. */ - - /* normally 'wm_homefile_read' will do this, - * however python is not initialized when called from this function. - * - * unlikely any handlers are set but its possible, - * note that recovering the last session does its own callbacks. */ - CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); - - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); - if (is_factory_startup) { - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST); - } - - wm_file_read_report(C, bmain); - - if (!G.background) { - CTX_wm_window_set(C, NULL); - } - } + { + Main *bmain = CTX_data_main(C); + /* note, logic here is from wm_file_read_post, + * call functions that depend on Python being initialized. */ + + /* normally 'wm_homefile_read' will do this, + * however python is not initialized when called from this function. + * + * unlikely any handlers are set but its possible, + * note that recovering the last session does its own callbacks. */ + CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); + + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); + if (is_factory_startup) { + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST); + } + + wm_file_read_report(C, bmain); + + if (!G.background) { + CTX_wm_window_set(C, NULL); + } + } } void WM_init_splash(bContext *C) { - if ((U.uiflag & USER_SPLASH_DISABLE) == 0) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *prevwin = CTX_wm_window(C); - - if (wm->windows.first) { - CTX_wm_window_set(C, wm->windows.first); - WM_operator_name_call(C, "WM_OT_splash", WM_OP_INVOKE_DEFAULT, NULL); - CTX_wm_window_set(C, prevwin); - } - } + if ((U.uiflag & USER_SPLASH_DISABLE) == 0) { + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *prevwin = CTX_wm_window(C); + + if (wm->windows.first) { + CTX_wm_window_set(C, wm->windows.first); + WM_operator_name_call(C, "WM_OT_splash", WM_OP_INVOKE_DEFAULT, NULL); + CTX_wm_window_set(C, prevwin); + } + } } /* free strings of open recent files */ static void free_openrecent(void) { - struct RecentFile *recent; + struct RecentFile *recent; - for (recent = G.recent_files.first; recent; recent = recent->next) { - MEM_freeN(recent->filepath); - } + for (recent = G.recent_files.first; recent; recent = recent->next) { + MEM_freeN(recent->filepath); + } - BLI_freelistN(&(G.recent_files)); + BLI_freelistN(&(G.recent_files)); } - #ifdef WIN32 /* Read console events until there is a key event. Also returns on any error. */ static void wait_for_console_key(void) { - HANDLE hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); - - if (!ELEM(hConsoleInput, NULL, INVALID_HANDLE_VALUE) && FlushConsoleInputBuffer(hConsoleInput)) { - for (;;) { - INPUT_RECORD buffer; - DWORD ignored; - - if (!ReadConsoleInput(hConsoleInput, &buffer, 1, &ignored)) { - break; - } - - if (buffer.EventType == KEY_EVENT) { - break; - } - } - } + HANDLE hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); + + if (!ELEM(hConsoleInput, NULL, INVALID_HANDLE_VALUE) && FlushConsoleInputBuffer(hConsoleInput)) { + for (;;) { + INPUT_RECORD buffer; + DWORD ignored; + + if (!ReadConsoleInput(hConsoleInput, &buffer, 1, &ignored)) { + break; + } + + if (buffer.EventType == KEY_EVENT) { + break; + } + } + } } #endif static int wm_exit_handler(bContext *C, const wmEvent *event, void *userdata) { - WM_exit(C); + WM_exit(C); - UNUSED_VARS(event, userdata); - return WM_UI_HANDLER_BREAK; + UNUSED_VARS(event, userdata); + return WM_UI_HANDLER_BREAK; } /** @@ -407,14 +412,14 @@ static int wm_exit_handler(bContext *C, const wmEvent *event, void *userdata) */ void wm_exit_schedule_delayed(const bContext *C) { - /* What we do here is a little bit hacky, but quite simple and doesn't require bigger - * changes: Add a handler wrapping WM_exit() to cause a delayed call of it. */ + /* What we do here is a little bit hacky, but quite simple and doesn't require bigger + * changes: Add a handler wrapping WM_exit() to cause a delayed call of it. */ - wmWindow *win = CTX_wm_window(C); + wmWindow *win = CTX_wm_window(C); - /* Use modal UI handler for now. Could add separate WM handlers or so, but probably not worth it. */ - WM_event_add_ui_handler(C, &win->modalhandlers, wm_exit_handler, NULL, NULL, 0); - WM_event_add_mousemove(C); /* ensure handler actually gets called */ + /* Use modal UI handler for now. Could add separate WM handlers or so, but probably not worth it. */ + WM_event_add_ui_handler(C, &win->modalhandlers, wm_exit_handler, NULL, NULL, 0); + WM_event_add_mousemove(C); /* ensure handler actually gets called */ } /** @@ -422,185 +427,185 @@ void wm_exit_schedule_delayed(const bContext *C) */ void WM_exit_ext(bContext *C, const bool do_python) { - wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL; + wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL; - /* first wrap up running stuff, we assume only the active WM is running */ - /* modal handlers are on window level freed, others too? */ - /* note; same code copied in wm_files.c */ - if (C && wm) { - wmWindow *win; + /* first wrap up running stuff, we assume only the active WM is running */ + /* modal handlers are on window level freed, others too? */ + /* note; same code copied in wm_files.c */ + if (C && wm) { + wmWindow *win; - if (!G.background) { - struct MemFile *undo_memfile = wm->undo_stack ? ED_undosys_stack_memfile_get_active(wm->undo_stack) : NULL; - if (undo_memfile != NULL) { - /* save the undo state as quit.blend */ - Main *bmain = CTX_data_main(C); - char filename[FILE_MAX]; - bool has_edited; - int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); + if (!G.background) { + struct MemFile *undo_memfile = wm->undo_stack ? + ED_undosys_stack_memfile_get_active(wm->undo_stack) : + NULL; + if (undo_memfile != NULL) { + /* save the undo state as quit.blend */ + Main *bmain = CTX_data_main(C); + char filename[FILE_MAX]; + bool has_edited; + int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); - BLI_make_file_string("/", filename, BKE_tempdir_base(), BLENDER_QUIT_FILE); + BLI_make_file_string("/", filename, BKE_tempdir_base(), BLENDER_QUIT_FILE); - has_edited = ED_editors_flush_edits(bmain, false); + has_edited = ED_editors_flush_edits(bmain, false); - if ((has_edited && BLO_write_file(bmain, filename, fileflags, NULL, NULL)) || - (undo_memfile && BLO_memfile_write_file(undo_memfile, filename))) - { - printf("Saved session recovery to '%s'\n", filename); - } - } - } + if ((has_edited && BLO_write_file(bmain, filename, fileflags, NULL, NULL)) || + (undo_memfile && BLO_memfile_write_file(undo_memfile, filename))) { + printf("Saved session recovery to '%s'\n", filename); + } + } + } - WM_jobs_kill_all(wm); + WM_jobs_kill_all(wm); - for (win = wm->windows.first; win; win = win->next) { + for (win = wm->windows.first; win; win = win->next) { - CTX_wm_window_set(C, win); /* needed by operator close callbacks */ - WM_event_remove_handlers(C, &win->handlers); - WM_event_remove_handlers(C, &win->modalhandlers); - ED_screen_exit(C, win, WM_window_get_active_screen(win)); - } - } + CTX_wm_window_set(C, win); /* needed by operator close callbacks */ + WM_event_remove_handlers(C, &win->handlers); + WM_event_remove_handlers(C, &win->modalhandlers); + ED_screen_exit(C, win, WM_window_get_active_screen(win)); + } + } - BLI_timer_free(); + BLI_timer_free(); - WM_paneltype_clear(); + WM_paneltype_clear(); - BKE_addon_pref_type_free(); - BKE_keyconfig_pref_type_free(); + BKE_addon_pref_type_free(); + BKE_keyconfig_pref_type_free(); - wm_operatortype_free(); - wm_dropbox_free(); - WM_menutype_free(); - WM_uilisttype_free(); + wm_operatortype_free(); + wm_dropbox_free(); + WM_menutype_free(); + WM_uilisttype_free(); - /* all non-screen and non-space stuff editors did, like editmode */ - if (C) { - Main *bmain = CTX_data_main(C); - ED_editors_exit(bmain, true); - } + /* all non-screen and non-space stuff editors did, like editmode */ + if (C) { + Main *bmain = CTX_data_main(C); + ED_editors_exit(bmain, true); + } - ED_undosys_type_free(); + ED_undosys_type_free(); - free_openrecent(); + free_openrecent(); - BKE_mball_cubeTable_free(); + BKE_mball_cubeTable_free(); - /* render code might still access databases */ - RE_FreeAllRender(); - RE_engines_exit(); + /* render code might still access databases */ + RE_FreeAllRender(); + RE_engines_exit(); - ED_preview_free_dbase(); /* frees a Main dbase, before BKE_blender_free! */ + ED_preview_free_dbase(); /* frees a Main dbase, before BKE_blender_free! */ - if (C && wm) { - /* Before BKE_blender_free! - since the ListBases get freed there. */ - wm_free_reports(C); - } + if (C && wm) { + /* Before BKE_blender_free! - since the ListBases get freed there. */ + wm_free_reports(C); + } - BKE_sequencer_free_clipboard(); /* sequencer.c */ - BKE_tracking_clipboard_free(); - BKE_mask_clipboard_free(); - BKE_vfont_clipboard_free(); - BKE_node_clipboard_free(); + BKE_sequencer_free_clipboard(); /* sequencer.c */ + BKE_tracking_clipboard_free(); + BKE_mask_clipboard_free(); + BKE_vfont_clipboard_free(); + BKE_node_clipboard_free(); #ifdef WITH_COMPOSITOR - COM_deinitialize(); + COM_deinitialize(); #endif - if (opengl_is_init) { + if (opengl_is_init) { #ifdef WITH_OPENSUBDIV - BKE_subsurf_osd_cleanup(); + BKE_subsurf_osd_cleanup(); #endif - GPU_free_unused_buffers(G_MAIN); - } - - BKE_blender_free(); /* blender.c, does entire library and spacetypes */ -// free_matcopybuf(); - ANIM_fcurves_copybuf_free(); - ANIM_drivers_copybuf_free(); - ANIM_driver_vars_copybuf_free(); - ANIM_fmodifiers_copybuf_free(); - ED_gpencil_anim_copybuf_free(); - ED_gpencil_strokes_copybuf_free(); - - /* free gizmo-maps after freeing blender, so no deleted data get accessed during cleaning up of areas */ - wm_gizmomaptypes_free(); - wm_gizmogrouptype_free(); - wm_gizmotype_free(); - - BLF_exit(); - - if (opengl_is_init) { - DRW_opengl_context_enable_ex(false); - GPU_pass_cache_free(); - GPU_exit(); - DRW_opengl_context_disable_ex(false); - DRW_opengl_context_destroy(); - } + GPU_free_unused_buffers(G_MAIN); + } + + BKE_blender_free(); /* blender.c, does entire library and spacetypes */ + // free_matcopybuf(); + ANIM_fcurves_copybuf_free(); + ANIM_drivers_copybuf_free(); + ANIM_driver_vars_copybuf_free(); + ANIM_fmodifiers_copybuf_free(); + ED_gpencil_anim_copybuf_free(); + ED_gpencil_strokes_copybuf_free(); + + /* free gizmo-maps after freeing blender, so no deleted data get accessed during cleaning up of areas */ + wm_gizmomaptypes_free(); + wm_gizmogrouptype_free(); + wm_gizmotype_free(); + + BLF_exit(); + + if (opengl_is_init) { + DRW_opengl_context_enable_ex(false); + GPU_pass_cache_free(); + GPU_exit(); + DRW_opengl_context_disable_ex(false); + DRW_opengl_context_destroy(); + } #ifdef WITH_INTERNATIONAL - BLF_free_unifont(); - BLF_free_unifont_mono(); - BLT_lang_free(); + BLF_free_unifont(); + BLF_free_unifont_mono(); + BLT_lang_free(); #endif - ANIM_keyingset_infos_exit(); - -// free_txt_data(); + ANIM_keyingset_infos_exit(); + // free_txt_data(); #ifdef WITH_PYTHON - /* option not to close python so we can use 'atexit' */ - if (do_python && ((C == NULL) || CTX_py_init_get(C))) { - /* XXX - old note */ - /* before BKE_blender_free so py's gc happens while library still exists */ - /* needed at least for a rare sigsegv that can happen in pydrivers */ - - /* Update for blender 2.5, move after BKE_blender_free because blender now holds references to PyObject's - * so decref'ing them after python ends causes bad problems every time - * the pyDriver bug can be fixed if it happens again we can deal with it then */ - BPY_python_end(); - } + /* option not to close python so we can use 'atexit' */ + if (do_python && ((C == NULL) || CTX_py_init_get(C))) { + /* XXX - old note */ + /* before BKE_blender_free so py's gc happens while library still exists */ + /* needed at least for a rare sigsegv that can happen in pydrivers */ + + /* Update for blender 2.5, move after BKE_blender_free because blender now holds references to PyObject's + * so decref'ing them after python ends causes bad problems every time + * the pyDriver bug can be fixed if it happens again we can deal with it then */ + BPY_python_end(); + } #else - (void)do_python; + (void)do_python; #endif - ED_file_exit(); /* for fsmenu */ + ED_file_exit(); /* for fsmenu */ - UI_exit(); - BKE_blender_userdef_data_free(&U, false); + UI_exit(); + BKE_blender_userdef_data_free(&U, false); - RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */ + RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */ - wm_ghost_exit(); + wm_ghost_exit(); - CTX_free(C); + CTX_free(C); - GHOST_DisposeSystemPaths(); + GHOST_DisposeSystemPaths(); - DNA_sdna_current_free(); + DNA_sdna_current_free(); - BLI_threadapi_exit(); + BLI_threadapi_exit(); - /* No need to call this early, rather do it late so that other pieces of Blender using sound may exit cleanly, - * see also T50676. */ - BKE_sound_exit(); + /* No need to call this early, rather do it late so that other pieces of Blender using sound may exit cleanly, + * see also T50676. */ + BKE_sound_exit(); - CLG_exit(); + CLG_exit(); - BKE_blender_atexit(); + BKE_blender_atexit(); - if (MEM_get_memory_blocks_in_use() != 0) { - size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use(); - printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n", - MEM_get_memory_blocks_in_use(), - (double)mem_in_use / 1024 / 1024); - MEM_printmemlist(); - } - wm_autosave_delete(); + if (MEM_get_memory_blocks_in_use() != 0) { + size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use(); + printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n", + MEM_get_memory_blocks_in_use(), + (double)mem_in_use / 1024 / 1024); + MEM_printmemlist(); + } + wm_autosave_delete(); - BKE_tempdir_session_purge(); + BKE_tempdir_session_purge(); } /** @@ -609,17 +614,17 @@ void WM_exit_ext(bContext *C, const bool do_python) */ void WM_exit(bContext *C) { - WM_exit_ext(C, 1); + WM_exit_ext(C, 1); - printf("\nBlender quit\n"); + printf("\nBlender quit\n"); #ifdef WIN32 - /* ask user to press a key when in debug mode */ - if (G.debug & G_DEBUG) { - printf("Press any key to exit . . .\n\n"); - wait_for_console_key(); - } + /* ask user to press a key when in debug mode */ + if (G.debug & G_DEBUG) { + printf("Press any key to exit . . .\n\n"); + wait_for_console_key(); + } #endif - exit(G.is_break == true); + exit(G.is_break == true); } diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index a1ebc29802f..6ce9dd70574 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -69,73 +69,72 @@ */ struct wmJob { - struct wmJob *next, *prev; - - /* job originating from, keep track of this when deleting windows */ - wmWindow *win; - - /* should store entire own context, for start, update, free */ - void *customdata; - /* to prevent cpu overhead, use this one which only gets called when job really starts, not in thread */ - void (*initjob)(void *); - /* this runs inside thread, and does full job */ - void (*startjob)(void *, short *stop, short *do_update, float *progress); - /* update gets called if thread defines so, and max once per timerstep */ - /* it runs outside thread, blocking blender, no drawing! */ - void (*update)(void *); - /* free entire customdata, doesn't run in thread */ - void (*free)(void *); - /* gets called when job is stopped, not in thread */ - void (*endjob)(void *); - - /* running jobs each have own timer */ - double timestep; - wmTimer *wt; - /* the notifier event timers should send */ - unsigned int note, endnote; - - - /* internal */ - void *owner; - int flag; - short suspended, running, ready, do_update, stop, job_type; - float progress; - - /* for display in header, identification */ - char name[128]; - - /* once running, we store this separately */ - void *run_customdata; - void (*run_free)(void *); - - /* we use BLI_threads api, but per job only 1 thread runs */ - ListBase threads; - - double start_time; - - /* ticket mutex for main thread locking while some job accesses - * data that the main thread might modify at the same time */ - TicketMutex *main_thread_mutex; + struct wmJob *next, *prev; + + /* job originating from, keep track of this when deleting windows */ + wmWindow *win; + + /* should store entire own context, for start, update, free */ + void *customdata; + /* to prevent cpu overhead, use this one which only gets called when job really starts, not in thread */ + void (*initjob)(void *); + /* this runs inside thread, and does full job */ + void (*startjob)(void *, short *stop, short *do_update, float *progress); + /* update gets called if thread defines so, and max once per timerstep */ + /* it runs outside thread, blocking blender, no drawing! */ + void (*update)(void *); + /* free entire customdata, doesn't run in thread */ + void (*free)(void *); + /* gets called when job is stopped, not in thread */ + void (*endjob)(void *); + + /* running jobs each have own timer */ + double timestep; + wmTimer *wt; + /* the notifier event timers should send */ + unsigned int note, endnote; + + /* internal */ + void *owner; + int flag; + short suspended, running, ready, do_update, stop, job_type; + float progress; + + /* for display in header, identification */ + char name[128]; + + /* once running, we store this separately */ + void *run_customdata; + void (*run_free)(void *); + + /* we use BLI_threads api, but per job only 1 thread runs */ + ListBase threads; + + double start_time; + + /* ticket mutex for main thread locking while some job accesses + * data that the main thread might modify at the same time */ + TicketMutex *main_thread_mutex; }; /* Main thread locking */ void WM_job_main_thread_lock_acquire(wmJob *wm_job) { - BLI_ticket_mutex_lock(wm_job->main_thread_mutex); + BLI_ticket_mutex_lock(wm_job->main_thread_mutex); } void WM_job_main_thread_lock_release(wmJob *wm_job) { - BLI_ticket_mutex_unlock(wm_job->main_thread_mutex); + BLI_ticket_mutex_unlock(wm_job->main_thread_mutex); } static void wm_job_main_thread_yield(wmJob *wm_job) { - /* unlock and lock the ticket mutex. because it's a fair mutex any job that - * is waiting to acquire the lock will get it first, before we can lock */ - BLI_ticket_mutex_unlock(wm_job->main_thread_mutex); - BLI_ticket_mutex_lock(wm_job->main_thread_mutex); + /* unlock and lock the ticket mutex. because it's a fair mutex any job that + * is waiting to acquire the lock will get it first, before we can lock */ + BLI_ticket_mutex_unlock(wm_job->main_thread_mutex); + BLI_ticket_mutex_lock(wm_job->main_thread_mutex); } /** @@ -143,31 +142,31 @@ static void wm_job_main_thread_yield(wmJob *wm_job) */ static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const int job_type) { - wmJob *wm_job; - - if (owner && job_type) { - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - if (wm_job->owner == owner && wm_job->job_type == job_type) { - return wm_job; - } - } - } - else if (owner) { - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - if (wm_job->owner == owner) { - return wm_job; - } - } - } - else if (job_type) { - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - if (wm_job->job_type == job_type) { - return wm_job; - } - } - } - - return NULL; + wmJob *wm_job; + + if (owner && job_type) { + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->owner == owner && wm_job->job_type == job_type) { + return wm_job; + } + } + } + else if (owner) { + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->owner == owner) { + return wm_job; + } + } + } + else if (job_type) { + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->job_type == job_type) { + return wm_job; + } + } + } + + return NULL; } /* ******************* public API ***************** */ @@ -178,182 +177,182 @@ static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const int job_type) * \note every owner only gets a single job, * adding a new one will stop running job and when stopped it starts the new one. */ -wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type) +wmJob *WM_jobs_get( + wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type) { - wmJob *wm_job = wm_job_find(wm, owner, job_type); + wmJob *wm_job = wm_job_find(wm, owner, job_type); - if (wm_job == NULL) { - wm_job = MEM_callocN(sizeof(wmJob), "new job"); + if (wm_job == NULL) { + wm_job = MEM_callocN(sizeof(wmJob), "new job"); - BLI_addtail(&wm->jobs, wm_job); - wm_job->win = win; - wm_job->owner = owner; - wm_job->flag = flag; - wm_job->job_type = job_type; - BLI_strncpy(wm_job->name, name, sizeof(wm_job->name)); + BLI_addtail(&wm->jobs, wm_job); + wm_job->win = win; + wm_job->owner = owner; + wm_job->flag = flag; + wm_job->job_type = job_type; + BLI_strncpy(wm_job->name, name, sizeof(wm_job->name)); - wm_job->main_thread_mutex = BLI_ticket_mutex_alloc(); - WM_job_main_thread_lock_acquire(wm_job); - } - /* else: a running job, be careful */ + wm_job->main_thread_mutex = BLI_ticket_mutex_alloc(); + WM_job_main_thread_lock_acquire(wm_job); + } + /* else: a running job, be careful */ - /* prevent creating a job with an invalid type */ - BLI_assert(wm_job->job_type != WM_JOB_TYPE_ANY); + /* prevent creating a job with an invalid type */ + BLI_assert(wm_job->job_type != WM_JOB_TYPE_ANY); - return wm_job; + return wm_job; } /* returns true if job runs, for UI (progress) indicators */ bool WM_jobs_test(wmWindowManager *wm, void *owner, int job_type) { - wmJob *wm_job; - - /* job can be running or about to run (suspended) */ - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - if (wm_job->owner == owner) { - if (job_type == WM_JOB_TYPE_ANY || (wm_job->job_type == job_type)) { - if (wm_job->running || wm_job->suspended) { - return true; - } - } - } - } - - return false; + wmJob *wm_job; + + /* job can be running or about to run (suspended) */ + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->owner == owner) { + if (job_type == WM_JOB_TYPE_ANY || (wm_job->job_type == job_type)) { + if (wm_job->running || wm_job->suspended) { + return true; + } + } + } + } + + return false; } float WM_jobs_progress(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); - if (wm_job && wm_job->flag & WM_JOB_PROGRESS) { - return wm_job->progress; - } + if (wm_job && wm_job->flag & WM_JOB_PROGRESS) { + return wm_job->progress; + } - return 0.0; + return 0.0; } static void wm_jobs_update_progress_bars(wmWindowManager *wm) { - float total_progress = 0.f; - float jobs_progress = 0; - - for (wmJob *wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - if (wm_job->threads.first && !wm_job->ready) { - if (wm_job->flag & WM_JOB_PROGRESS) { - /* accumulate global progress for running jobs */ - jobs_progress++; - total_progress += wm_job->progress; - } - } - } - - /* if there are running jobs, set the global progress indicator */ - if (jobs_progress > 0) { - wmWindow *win; - float progress = total_progress / (float)jobs_progress; - - for (win = wm->windows.first; win; win = win->next) { - WM_progress_set(win, progress); - } - } - else { - wmWindow *win; - - for (win = wm->windows.first; win; win = win->next) { - WM_progress_clear(win); - } - } - + float total_progress = 0.f; + float jobs_progress = 0; + + for (wmJob *wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->threads.first && !wm_job->ready) { + if (wm_job->flag & WM_JOB_PROGRESS) { + /* accumulate global progress for running jobs */ + jobs_progress++; + total_progress += wm_job->progress; + } + } + } + + /* if there are running jobs, set the global progress indicator */ + if (jobs_progress > 0) { + wmWindow *win; + float progress = total_progress / (float)jobs_progress; + + for (win = wm->windows.first; win; win = win->next) { + WM_progress_set(win, progress); + } + } + else { + wmWindow *win; + + for (win = wm->windows.first; win; win = win->next) { + WM_progress_clear(win); + } + } } /* time that job started */ double WM_jobs_starttime(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); - if (wm_job && wm_job->flag & WM_JOB_PROGRESS) { - return wm_job->start_time; - } + if (wm_job && wm_job->flag & WM_JOB_PROGRESS) { + return wm_job->start_time; + } - return 0; + return 0; } char *WM_jobs_name(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); - if (wm_job) { - return wm_job->name; - } + if (wm_job) { + return wm_job->name; + } - return NULL; + return NULL; } void *WM_jobs_customdata(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); - if (wm_job) { - return WM_jobs_customdata_get(wm_job); - } + if (wm_job) { + return WM_jobs_customdata_get(wm_job); + } - return NULL; + return NULL; } void *WM_jobs_customdata_from_type(wmWindowManager *wm, int job_type) { - wmJob *wm_job = wm_job_find(wm, NULL, job_type); + wmJob *wm_job = wm_job_find(wm, NULL, job_type); - if (wm_job) { - return WM_jobs_customdata_get(wm_job); - } + if (wm_job) { + return WM_jobs_customdata_get(wm_job); + } - return NULL; + return NULL; } bool WM_jobs_is_running(wmJob *wm_job) { - return wm_job->running; + return wm_job->running; } bool WM_jobs_is_stopped(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); - return wm_job ? wm_job->stop : true; /* XXX to be redesigned properly. */ + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); + return wm_job ? wm_job->stop : true; /* XXX to be redesigned properly. */ } void *WM_jobs_customdata_get(wmJob *wm_job) { - if (!wm_job->customdata) { - return wm_job->run_customdata; - } - else { - return wm_job->customdata; - } + if (!wm_job->customdata) { + return wm_job->run_customdata; + } + else { + return wm_job->customdata; + } } void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void (*free)(void *)) { - /* pending job? just free */ - if (wm_job->customdata) { - wm_job->free(wm_job->customdata); - } - - wm_job->customdata = customdata; - wm_job->free = free; - - if (wm_job->running) { - /* signal job to end */ - wm_job->stop = true; - } + /* pending job? just free */ + if (wm_job->customdata) { + wm_job->free(wm_job->customdata); + } + + wm_job->customdata = customdata; + wm_job->free = free; + + if (wm_job->running) { + /* signal job to end */ + wm_job->stop = true; + } } void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote) { - wm_job->timestep = timestep; - wm_job->note = note; - wm_job->endnote = endnote; + wm_job->timestep = timestep; + wm_job->note = note; + wm_job->endnote = endnote; } void WM_jobs_callbacks(wmJob *wm_job, @@ -362,69 +361,69 @@ void WM_jobs_callbacks(wmJob *wm_job, void (*update)(void *), void (*endjob)(void *)) { - wm_job->startjob = startjob; - wm_job->initjob = initjob; - wm_job->update = update; - wm_job->endjob = endjob; + wm_job->startjob = startjob; + wm_job->initjob = initjob; + wm_job->update = update; + wm_job->endjob = endjob; } static void *do_job_thread(void *job_v) { - wmJob *wm_job = job_v; + wmJob *wm_job = job_v; - BLI_thread_put_thread_on_fast_node(); - wm_job->startjob(wm_job->run_customdata, &wm_job->stop, &wm_job->do_update, &wm_job->progress); - wm_job->ready = true; + BLI_thread_put_thread_on_fast_node(); + wm_job->startjob(wm_job->run_customdata, &wm_job->stop, &wm_job->do_update, &wm_job->progress); + wm_job->ready = true; - return NULL; + return NULL; } /* don't allow same startjob to be executed twice */ static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test) { - wmJob *wm_job; - bool suspend = false; - - /* job added with suspend flag, we wait 1 timer step before activating it */ - if (test->flag & WM_JOB_SUSPEND) { - suspend = true; - test->flag &= ~WM_JOB_SUSPEND; - } - else { - /* check other jobs */ - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - /* obvious case, no test needed */ - if (wm_job == test || !wm_job->running) { - continue; - } - - /* if new job is not render, then check for same startjob */ - if (0 == (test->flag & WM_JOB_EXCL_RENDER)) { - if (wm_job->startjob != test->startjob) { - continue; - } - } - - /* if new job is render, any render job should be stopped */ - if (test->flag & WM_JOB_EXCL_RENDER) { - if (0 == (wm_job->flag & WM_JOB_EXCL_RENDER)) { - continue; - } - } - - suspend = true; - - /* if this job has higher priority, stop others */ - if (test->flag & WM_JOB_PRIORITY) { - wm_job->stop = true; - // printf("job stopped: %s\n", wm_job->name); - } - } - } - - /* Possible suspend ourselves, waiting for other jobs, or de-suspend. */ - test->suspended = suspend; - // if (suspend) printf("job suspended: %s\n", test->name); + wmJob *wm_job; + bool suspend = false; + + /* job added with suspend flag, we wait 1 timer step before activating it */ + if (test->flag & WM_JOB_SUSPEND) { + suspend = true; + test->flag &= ~WM_JOB_SUSPEND; + } + else { + /* check other jobs */ + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + /* obvious case, no test needed */ + if (wm_job == test || !wm_job->running) { + continue; + } + + /* if new job is not render, then check for same startjob */ + if (0 == (test->flag & WM_JOB_EXCL_RENDER)) { + if (wm_job->startjob != test->startjob) { + continue; + } + } + + /* if new job is render, any render job should be stopped */ + if (test->flag & WM_JOB_EXCL_RENDER) { + if (0 == (wm_job->flag & WM_JOB_EXCL_RENDER)) { + continue; + } + } + + suspend = true; + + /* if this job has higher priority, stop others */ + if (test->flag & WM_JOB_PRIORITY) { + wm_job->stop = true; + // printf("job stopped: %s\n", wm_job->name); + } + } + } + + /* Possible suspend ourselves, waiting for other jobs, or de-suspend. */ + test->suspended = suspend; + // if (suspend) printf("job suspended: %s\n", test->name); } /** @@ -433,278 +432,278 @@ static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test) */ void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job) { - if (wm_job->running) { - /* signal job to end and restart */ - wm_job->stop = true; - // printf("job started a running job, ending... %s\n", wm_job->name); - } - else { - - if (wm_job->customdata && wm_job->startjob) { - - wm_jobs_test_suspend_stop(wm, wm_job); - - if (wm_job->suspended == false) { - /* copy to ensure proper free in end */ - wm_job->run_customdata = wm_job->customdata; - wm_job->run_free = wm_job->free; - wm_job->free = NULL; - wm_job->customdata = NULL; - wm_job->running = true; - - if (wm_job->initjob) { - wm_job->initjob(wm_job->run_customdata); - } - - wm_job->stop = false; - wm_job->ready = false; - wm_job->progress = 0.0; - - // printf("job started: %s\n", wm_job->name); - - BLI_threadpool_init(&wm_job->threads, do_job_thread, 1); - BLI_threadpool_insert(&wm_job->threads, wm_job); - } - - /* restarted job has timer already */ - if (wm_job->wt == NULL) { - wm_job->wt = WM_event_add_timer(wm, wm_job->win, TIMERJOBS, wm_job->timestep); - } - - wm_job->start_time = PIL_check_seconds_timer(); - } - else { - printf("job fails, not initialized\n"); - } - } + if (wm_job->running) { + /* signal job to end and restart */ + wm_job->stop = true; + // printf("job started a running job, ending... %s\n", wm_job->name); + } + else { + + if (wm_job->customdata && wm_job->startjob) { + + wm_jobs_test_suspend_stop(wm, wm_job); + + if (wm_job->suspended == false) { + /* copy to ensure proper free in end */ + wm_job->run_customdata = wm_job->customdata; + wm_job->run_free = wm_job->free; + wm_job->free = NULL; + wm_job->customdata = NULL; + wm_job->running = true; + + if (wm_job->initjob) { + wm_job->initjob(wm_job->run_customdata); + } + + wm_job->stop = false; + wm_job->ready = false; + wm_job->progress = 0.0; + + // printf("job started: %s\n", wm_job->name); + + BLI_threadpool_init(&wm_job->threads, do_job_thread, 1); + BLI_threadpool_insert(&wm_job->threads, wm_job); + } + + /* restarted job has timer already */ + if (wm_job->wt == NULL) { + wm_job->wt = WM_event_add_timer(wm, wm_job->win, TIMERJOBS, wm_job->timestep); + } + + wm_job->start_time = PIL_check_seconds_timer(); + } + else { + printf("job fails, not initialized\n"); + } + } } static void wm_job_free(wmWindowManager *wm, wmJob *wm_job) { - BLI_remlink(&wm->jobs, wm_job); - WM_job_main_thread_lock_release(wm_job); - BLI_ticket_mutex_free(wm_job->main_thread_mutex); - MEM_freeN(wm_job); + BLI_remlink(&wm->jobs, wm_job); + WM_job_main_thread_lock_release(wm_job); + BLI_ticket_mutex_free(wm_job->main_thread_mutex); + MEM_freeN(wm_job); } /* stop job, end thread, free data completely */ static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *wm_job) { - bool update_progress = (wm_job->flag & WM_JOB_PROGRESS) != 0; - - if (wm_job->running) { - /* signal job to end */ - wm_job->stop = true; - - WM_job_main_thread_lock_release(wm_job); - BLI_threadpool_end(&wm_job->threads); - WM_job_main_thread_lock_acquire(wm_job); - - if (wm_job->endjob) { - wm_job->endjob(wm_job->run_customdata); - } - } - - if (wm_job->wt) { - WM_event_remove_timer(wm, wm_job->win, wm_job->wt); - } - if (wm_job->customdata) { - wm_job->free(wm_job->customdata); - } - if (wm_job->run_customdata) { - wm_job->run_free(wm_job->run_customdata); - } - - /* remove wm_job */ - wm_job_free(wm, wm_job); - - /* Update progress bars in windows. */ - if (update_progress) { - wm_jobs_update_progress_bars(wm); - } + bool update_progress = (wm_job->flag & WM_JOB_PROGRESS) != 0; + + if (wm_job->running) { + /* signal job to end */ + wm_job->stop = true; + + WM_job_main_thread_lock_release(wm_job); + BLI_threadpool_end(&wm_job->threads); + WM_job_main_thread_lock_acquire(wm_job); + + if (wm_job->endjob) { + wm_job->endjob(wm_job->run_customdata); + } + } + + if (wm_job->wt) { + WM_event_remove_timer(wm, wm_job->win, wm_job->wt); + } + if (wm_job->customdata) { + wm_job->free(wm_job->customdata); + } + if (wm_job->run_customdata) { + wm_job->run_free(wm_job->run_customdata); + } + + /* remove wm_job */ + wm_job_free(wm, wm_job); + + /* Update progress bars in windows. */ + if (update_progress) { + wm_jobs_update_progress_bars(wm); + } } /* wait until every job ended */ void WM_jobs_kill_all(wmWindowManager *wm) { - wmJob *wm_job; - - while ((wm_job = wm->jobs.first)) { - wm_jobs_kill_job(wm, wm_job); - } + wmJob *wm_job; + while ((wm_job = wm->jobs.first)) { + wm_jobs_kill_job(wm, wm_job); + } } /* wait until every job ended, except for one owner (used in undo to keep screen job alive) */ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) { - wmJob *wm_job, *next_job; + wmJob *wm_job, *next_job; - for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { - next_job = wm_job->next; + for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { + next_job = wm_job->next; - if (wm_job->owner != owner) { - wm_jobs_kill_job(wm, wm_job); - } - } + if (wm_job->owner != owner) { + wm_jobs_kill_job(wm, wm_job); + } + } } - void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type) { - wmJob *wm_job, *next_job; + wmJob *wm_job, *next_job; - for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { - next_job = wm_job->next; + for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { + next_job = wm_job->next; - if (!owner || wm_job->owner == owner) { - if (job_type == WM_JOB_TYPE_ANY || wm_job->job_type == job_type) { - wm_jobs_kill_job(wm, wm_job); - } - } - } + if (!owner || wm_job->owner == owner) { + if (job_type == WM_JOB_TYPE_ANY || wm_job->job_type == job_type) { + wm_jobs_kill_job(wm, wm_job); + } + } + } } /* signal job(s) from this owner or callback to stop, timer is required to get handled */ void WM_jobs_stop(wmWindowManager *wm, void *owner, void *startjob) { - wmJob *wm_job; - - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - if (wm_job->owner == owner || wm_job->startjob == startjob) { - if (wm_job->running) { - wm_job->stop = true; - } - } - } + wmJob *wm_job; + + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->owner == owner || wm_job->startjob == startjob) { + if (wm_job->running) { + wm_job->stop = true; + } + } + } } /* actually terminate thread and job timer */ -void WM_jobs_kill(wmWindowManager *wm, void *owner, void (*startjob)(void *, short int *, short int *, float *)) +void WM_jobs_kill(wmWindowManager *wm, + void *owner, + void (*startjob)(void *, short int *, short int *, float *)) { - wmJob *wm_job; - - wm_job = wm->jobs.first; - while (wm_job) { - if (wm_job->owner == owner || wm_job->startjob == startjob) { - wmJob *wm_job_kill = wm_job; - wm_job = wm_job->next; - wm_jobs_kill_job(wm, wm_job_kill); - } - else { - wm_job = wm_job->next; - } - } + wmJob *wm_job; + + wm_job = wm->jobs.first; + while (wm_job) { + if (wm_job->owner == owner || wm_job->startjob == startjob) { + wmJob *wm_job_kill = wm_job; + wm_job = wm_job->next; + wm_jobs_kill_job(wm, wm_job_kill); + } + else { + wm_job = wm_job->next; + } + } } - /* kill job entirely, also removes timer itself */ void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt) { - wmJob *wm_job; - - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - if (wm_job->wt == wt) { - wm_jobs_kill_job(wm, wm_job); - return; - } - } + wmJob *wm_job; + + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->wt == wt) { + wm_jobs_kill_job(wm, wm_job); + return; + } + } } /* hardcoded to event TIMERJOBS */ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt) { - wmJob *wm_job, *wm_jobnext; - - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_jobnext) { - wm_jobnext = wm_job->next; - - if (wm_job->wt == wt) { - - /* running threads */ - if (wm_job->threads.first) { - - /* let threads get temporary lock over main thread if needed */ - wm_job_main_thread_yield(wm_job); - - /* always call note and update when ready */ - if (wm_job->do_update || wm_job->ready) { - if (wm_job->update) { - wm_job->update(wm_job->run_customdata); - } - if (wm_job->note) { - WM_event_add_notifier(C, wm_job->note, NULL); - } - - if (wm_job->flag & WM_JOB_PROGRESS) { - WM_event_add_notifier(C, NC_WM | ND_JOB, NULL); - } - wm_job->do_update = false; - } - - if (wm_job->ready) { - if (wm_job->endjob) { - wm_job->endjob(wm_job->run_customdata); - } - - /* free own data */ - wm_job->run_free(wm_job->run_customdata); - wm_job->run_customdata = NULL; - wm_job->run_free = NULL; - - // if (wm_job->stop) printf("job ready but stopped %s\n", wm_job->name); - // else printf("job finished %s\n", wm_job->name); - - if (G.debug & G_DEBUG_JOBS) { - printf("Job '%s' finished in %f seconds\n", wm_job->name, - PIL_check_seconds_timer() - wm_job->start_time); - } - - wm_job->running = false; - - WM_job_main_thread_lock_release(wm_job); - BLI_threadpool_end(&wm_job->threads); - WM_job_main_thread_lock_acquire(wm_job); - - if (wm_job->endnote) { - WM_event_add_notifier(C, wm_job->endnote, NULL); - } - - WM_event_add_notifier(C, NC_WM | ND_JOB, NULL); - - /* new job added for wm_job? */ - if (wm_job->customdata) { - // printf("job restarted with new data %s\n", wm_job->name); - WM_jobs_start(wm, wm_job); - } - else { - WM_event_remove_timer(wm, wm_job->win, wm_job->wt); - wm_job->wt = NULL; - - /* remove wm_job */ - wm_job_free(wm, wm_job); - } - } - } - else if (wm_job->suspended) { - WM_jobs_start(wm, wm_job); - } - } - } - - /* Update progress bars in windows. */ - wm_jobs_update_progress_bars(wm); + wmJob *wm_job, *wm_jobnext; + + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_jobnext) { + wm_jobnext = wm_job->next; + + if (wm_job->wt == wt) { + + /* running threads */ + if (wm_job->threads.first) { + + /* let threads get temporary lock over main thread if needed */ + wm_job_main_thread_yield(wm_job); + + /* always call note and update when ready */ + if (wm_job->do_update || wm_job->ready) { + if (wm_job->update) { + wm_job->update(wm_job->run_customdata); + } + if (wm_job->note) { + WM_event_add_notifier(C, wm_job->note, NULL); + } + + if (wm_job->flag & WM_JOB_PROGRESS) { + WM_event_add_notifier(C, NC_WM | ND_JOB, NULL); + } + wm_job->do_update = false; + } + + if (wm_job->ready) { + if (wm_job->endjob) { + wm_job->endjob(wm_job->run_customdata); + } + + /* free own data */ + wm_job->run_free(wm_job->run_customdata); + wm_job->run_customdata = NULL; + wm_job->run_free = NULL; + + // if (wm_job->stop) printf("job ready but stopped %s\n", wm_job->name); + // else printf("job finished %s\n", wm_job->name); + + if (G.debug & G_DEBUG_JOBS) { + printf("Job '%s' finished in %f seconds\n", + wm_job->name, + PIL_check_seconds_timer() - wm_job->start_time); + } + + wm_job->running = false; + + WM_job_main_thread_lock_release(wm_job); + BLI_threadpool_end(&wm_job->threads); + WM_job_main_thread_lock_acquire(wm_job); + + if (wm_job->endnote) { + WM_event_add_notifier(C, wm_job->endnote, NULL); + } + + WM_event_add_notifier(C, NC_WM | ND_JOB, NULL); + + /* new job added for wm_job? */ + if (wm_job->customdata) { + // printf("job restarted with new data %s\n", wm_job->name); + WM_jobs_start(wm, wm_job); + } + else { + WM_event_remove_timer(wm, wm_job->win, wm_job->wt); + wm_job->wt = NULL; + + /* remove wm_job */ + wm_job_free(wm, wm_job); + } + } + } + else if (wm_job->suspended) { + WM_jobs_start(wm, wm_job); + } + } + } + + /* Update progress bars in windows. */ + wm_jobs_update_progress_bars(wm); } bool WM_jobs_has_running(wmWindowManager *wm) { - wmJob *wm_job; + wmJob *wm_job; - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { - if (wm_job->running) { - return true; - } - } + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->running) { + return true; + } + } - return false; + return false; } diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index ba9accb5dee..3feae3d7dfc 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -57,8 +57,8 @@ #include "wm_event_types.h" struct wmKeyMapItemFind_Params { - bool (*filter_fn)(const wmKeyMap *km, const wmKeyMapItem *kmi, void *user_data); - void *user_data; + bool (*filter_fn)(const wmKeyMap *km, const wmKeyMapItem *kmi, void *user_data); + void *user_data; }; /******************************* Keymap Item ********************************** @@ -66,41 +66,41 @@ struct wmKeyMapItemFind_Params { static wmKeyMapItem *wm_keymap_item_copy(wmKeyMapItem *kmi) { - wmKeyMapItem *kmin = MEM_dupallocN(kmi); + wmKeyMapItem *kmin = MEM_dupallocN(kmi); - kmin->prev = kmin->next = NULL; - kmin->flag &= ~KMI_UPDATE; + kmin->prev = kmin->next = NULL; + kmin->flag &= ~KMI_UPDATE; - if (kmin->properties) { - kmin->ptr = MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr"); - WM_operator_properties_create(kmin->ptr, kmin->idname); + if (kmin->properties) { + kmin->ptr = MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr"); + WM_operator_properties_create(kmin->ptr, kmin->idname); - kmin->properties = IDP_CopyProperty(kmin->properties); - kmin->ptr->data = kmin->properties; - } - else { - kmin->properties = NULL; - kmin->ptr = NULL; - } + kmin->properties = IDP_CopyProperty(kmin->properties); + kmin->ptr->data = kmin->properties; + } + else { + kmin->properties = NULL; + kmin->ptr = NULL; + } - return kmin; + return kmin; } static void wm_keymap_item_free(wmKeyMapItem *kmi) { - /* not kmi itself */ - if (kmi->ptr) { - WM_operator_properties_free(kmi->ptr); - MEM_freeN(kmi->ptr); - kmi->ptr = NULL; - kmi->properties = NULL; - } + /* not kmi itself */ + if (kmi->ptr) { + WM_operator_properties_free(kmi->ptr); + MEM_freeN(kmi->ptr); + kmi->ptr = NULL; + kmi->properties = NULL; + } } static void wm_keymap_item_properties_set(wmKeyMapItem *kmi) { - WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname); - WM_operator_properties_sanitize(kmi->ptr, 1); + WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname); + WM_operator_properties_sanitize(kmi->ptr, 1); } /** @@ -108,152 +108,144 @@ static void wm_keymap_item_properties_set(wmKeyMapItem *kmi) */ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi) { - if (kmi->idname[0] == 0) { - BLI_assert(kmi->ptr == NULL); - return; - } - - if (kmi->ptr == NULL) { - wm_keymap_item_properties_set(kmi); - } - else { - wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0); - if (ot) { - if (ot->srna != kmi->ptr->type) { - /* matches wm_keymap_item_properties_set but doesn't alloc new ptr */ - WM_operator_properties_create_ptr(kmi->ptr, ot); - /* 'kmi->ptr->data' NULL'd above, keep using existing properties. - * Note: the operators property types may have changed, - * we will need a more comprehensive sanitize function to support this properly. - */ - if (kmi->properties) { - kmi->ptr->data = kmi->properties; - } - WM_operator_properties_sanitize(kmi->ptr, 1); - } - } - else { - /* zombie keymap item */ - wm_keymap_item_free(kmi); - } - } + if (kmi->idname[0] == 0) { + BLI_assert(kmi->ptr == NULL); + return; + } + + if (kmi->ptr == NULL) { + wm_keymap_item_properties_set(kmi); + } + else { + wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0); + if (ot) { + if (ot->srna != kmi->ptr->type) { + /* matches wm_keymap_item_properties_set but doesn't alloc new ptr */ + WM_operator_properties_create_ptr(kmi->ptr, ot); + /* 'kmi->ptr->data' NULL'd above, keep using existing properties. + * Note: the operators property types may have changed, + * we will need a more comprehensive sanitize function to support this properly. + */ + if (kmi->properties) { + kmi->ptr->data = kmi->properties; + } + WM_operator_properties_sanitize(kmi->ptr, 1); + } + } + else { + /* zombie keymap item */ + wm_keymap_item_free(kmi); + } + } } static void wm_keyconfig_properties_update_ot(ListBase *km_lb) { - wmKeyMap *km; - wmKeyMapItem *kmi; + wmKeyMap *km; + wmKeyMapItem *kmi; - for (km = km_lb->first; km; km = km->next) { - wmKeyMapDiffItem *kmdi; + for (km = km_lb->first; km; km = km->next) { + wmKeyMapDiffItem *kmdi; - for (kmi = km->items.first; kmi; kmi = kmi->next) { - wm_keymap_item_properties_update_ot(kmi); - } + for (kmi = km->items.first; kmi; kmi = kmi->next) { + wm_keymap_item_properties_update_ot(kmi); + } - for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { - if (kmdi->add_item) { - wm_keymap_item_properties_update_ot(kmdi->add_item); - } - if (kmdi->remove_item) { - wm_keymap_item_properties_update_ot(kmdi->remove_item); - } - } - } + for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { + if (kmdi->add_item) { + wm_keymap_item_properties_update_ot(kmdi->add_item); + } + if (kmdi->remove_item) { + wm_keymap_item_properties_update_ot(kmdi->remove_item); + } + } + } } static bool wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b) { - return (STREQ(a->idname, b->idname) && - /* We do not really care about which Main we pass here, tbh. */ - RNA_struct_equals(G_MAIN, a->ptr, b->ptr, RNA_EQ_UNSET_MATCH_NONE) && - (a->flag & KMI_INACTIVE) == (b->flag & KMI_INACTIVE) && - a->propvalue == b->propvalue); + return (STREQ(a->idname, b->idname) && + /* We do not really care about which Main we pass here, tbh. */ + RNA_struct_equals(G_MAIN, a->ptr, b->ptr, RNA_EQ_UNSET_MATCH_NONE) && + (a->flag & KMI_INACTIVE) == (b->flag & KMI_INACTIVE) && a->propvalue == b->propvalue); } static bool wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b) { - return (wm_keymap_item_equals_result(a, b) && - a->type == b->type && - a->val == b->val && - a->shift == b->shift && - a->ctrl == b->ctrl && - a->alt == b->alt && - a->oskey == b->oskey && - a->keymodifier == b->keymodifier && - a->maptype == b->maptype); + return (wm_keymap_item_equals_result(a, b) && a->type == b->type && a->val == b->val && + a->shift == b->shift && a->ctrl == b->ctrl && a->alt == b->alt && a->oskey == b->oskey && + a->keymodifier == b->keymodifier && a->maptype == b->maptype); } /* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */ void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties) { - if (LIKELY(kmi->ptr)) { - WM_operator_properties_free(kmi->ptr); - MEM_freeN(kmi->ptr); + if (LIKELY(kmi->ptr)) { + WM_operator_properties_free(kmi->ptr); + MEM_freeN(kmi->ptr); - kmi->ptr = NULL; - } + kmi->ptr = NULL; + } - kmi->properties = properties; + kmi->properties = properties; - wm_keymap_item_properties_set(kmi); + wm_keymap_item_properties_set(kmi); } int WM_keymap_map_type_get(wmKeyMapItem *kmi) { - if (ISTIMER(kmi->type)) { - return KMI_TYPE_TIMER; - } - if (ISKEYBOARD(kmi->type)) { - return KMI_TYPE_KEYBOARD; - } - if (ISTWEAK(kmi->type)) { - return KMI_TYPE_TWEAK; - } - if (ISMOUSE(kmi->type)) { - return KMI_TYPE_MOUSE; - } - if (ISNDOF(kmi->type)) { - return KMI_TYPE_NDOF; - } - if (kmi->type == KM_TEXTINPUT) { - return KMI_TYPE_TEXTINPUT; - } - if (ELEM(kmi->type, TABLET_STYLUS, TABLET_ERASER)) { - return KMI_TYPE_MOUSE; - } - return KMI_TYPE_KEYBOARD; + if (ISTIMER(kmi->type)) { + return KMI_TYPE_TIMER; + } + if (ISKEYBOARD(kmi->type)) { + return KMI_TYPE_KEYBOARD; + } + if (ISTWEAK(kmi->type)) { + return KMI_TYPE_TWEAK; + } + if (ISMOUSE(kmi->type)) { + return KMI_TYPE_MOUSE; + } + if (ISNDOF(kmi->type)) { + return KMI_TYPE_NDOF; + } + if (kmi->type == KM_TEXTINPUT) { + return KMI_TYPE_TEXTINPUT; + } + if (ELEM(kmi->type, TABLET_STYLUS, TABLET_ERASER)) { + return KMI_TYPE_MOUSE; + } + return KMI_TYPE_KEYBOARD; } - /**************************** Keymap Diff Item ********************************* * Item in a diff keymap, used for saving diff of keymaps in user preferences */ static wmKeyMapDiffItem *wm_keymap_diff_item_copy(wmKeyMapDiffItem *kmdi) { - wmKeyMapDiffItem *kmdin = MEM_dupallocN(kmdi); + wmKeyMapDiffItem *kmdin = MEM_dupallocN(kmdi); - kmdin->next = kmdin->prev = NULL; - if (kmdi->add_item) { - kmdin->add_item = wm_keymap_item_copy(kmdi->add_item); - } - if (kmdi->remove_item) { - kmdin->remove_item = wm_keymap_item_copy(kmdi->remove_item); - } + kmdin->next = kmdin->prev = NULL; + if (kmdi->add_item) { + kmdin->add_item = wm_keymap_item_copy(kmdi->add_item); + } + if (kmdi->remove_item) { + kmdin->remove_item = wm_keymap_item_copy(kmdi->remove_item); + } - return kmdin; + return kmdin; } static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi) { - if (kmdi->remove_item) { - wm_keymap_item_free(kmdi->remove_item); - MEM_freeN(kmdi->remove_item); - } - if (kmdi->add_item) { - wm_keymap_item_free(kmdi->add_item); - MEM_freeN(kmdi->add_item); - } + if (kmdi->remove_item) { + wm_keymap_item_free(kmdi->remove_item); + MEM_freeN(kmdi->remove_item); + } + if (kmdi->add_item) { + wm_keymap_item_free(kmdi->add_item); + MEM_freeN(kmdi->add_item); + } } /***************************** Key Configuration ****************************** @@ -262,98 +254,98 @@ static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi) wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname, bool user_defined) { - wmKeyConfig *keyconf = BLI_findstring(&wm->keyconfigs, idname, offsetof(wmKeyConfig, idname)); - if (keyconf) { - if (keyconf == wm->defaultconf) { - /* For default configuration, we need to keep keymap - * modal items and poll functions intact. */ - for (wmKeyMap *km = keyconf->keymaps.first; km; km = km->next) { - WM_keymap_clear(km); - } - } - else { - /* For user defined key configuration, clear all keymaps. */ - WM_keyconfig_clear(keyconf); - } + wmKeyConfig *keyconf = BLI_findstring(&wm->keyconfigs, idname, offsetof(wmKeyConfig, idname)); + if (keyconf) { + if (keyconf == wm->defaultconf) { + /* For default configuration, we need to keep keymap + * modal items and poll functions intact. */ + for (wmKeyMap *km = keyconf->keymaps.first; km; km = km->next) { + WM_keymap_clear(km); + } + } + else { + /* For user defined key configuration, clear all keymaps. */ + WM_keyconfig_clear(keyconf); + } - return keyconf; - } + return keyconf; + } - /* Create new configuration. */ - keyconf = MEM_callocN(sizeof(wmKeyConfig), "wmKeyConfig"); - BLI_strncpy(keyconf->idname, idname, sizeof(keyconf->idname)); - BLI_addtail(&wm->keyconfigs, keyconf); + /* Create new configuration. */ + keyconf = MEM_callocN(sizeof(wmKeyConfig), "wmKeyConfig"); + BLI_strncpy(keyconf->idname, idname, sizeof(keyconf->idname)); + BLI_addtail(&wm->keyconfigs, keyconf); - if (user_defined) { - keyconf->flag |= KEYCONF_USER; - } + if (user_defined) { + keyconf->flag |= KEYCONF_USER; + } - return keyconf; + return keyconf; } wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname) { - return WM_keyconfig_new(wm, idname, true); + return WM_keyconfig_new(wm, idname, true); } bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) { - if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) { - if (STREQLEN(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr))) { - BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr)); - WM_keyconfig_update_tag(NULL, NULL); - } + if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) { + if (STREQLEN(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr))) { + BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr)); + WM_keyconfig_update_tag(NULL, NULL); + } - BLI_remlink(&wm->keyconfigs, keyconf); - WM_keyconfig_free(keyconf); + BLI_remlink(&wm->keyconfigs, keyconf); + WM_keyconfig_free(keyconf); - return true; - } - else { - return false; - } + return true; + } + else { + return false; + } } void WM_keyconfig_clear(wmKeyConfig *keyconf) { - for (wmKeyMap *km = keyconf->keymaps.first; km; km = km->next) { - WM_keymap_clear(km); - } + for (wmKeyMap *km = keyconf->keymaps.first; km; km = km->next) { + WM_keymap_clear(km); + } - BLI_freelistN(&keyconf->keymaps); + BLI_freelistN(&keyconf->keymaps); } void WM_keyconfig_free(wmKeyConfig *keyconf) { - WM_keyconfig_clear(keyconf); - MEM_freeN(keyconf); + WM_keyconfig_clear(keyconf); + MEM_freeN(keyconf); } static wmKeyConfig *WM_keyconfig_active(wmWindowManager *wm) { - wmKeyConfig *keyconf; + wmKeyConfig *keyconf; - /* first try from preset */ - keyconf = BLI_findstring(&wm->keyconfigs, U.keyconfigstr, offsetof(wmKeyConfig, idname)); - if (keyconf) { - return keyconf; - } + /* first try from preset */ + keyconf = BLI_findstring(&wm->keyconfigs, U.keyconfigstr, offsetof(wmKeyConfig, idname)); + if (keyconf) { + return keyconf; + } - /* otherwise use default */ - return wm->defaultconf; + /* otherwise use default */ + return wm->defaultconf; } void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname) { - /* setting a different key configuration as active: we ensure all is - * updated properly before and after making the change */ + /* setting a different key configuration as active: we ensure all is + * updated properly before and after making the change */ - WM_keyconfig_update(wm); + WM_keyconfig_update(wm); - BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr)); + BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr)); - WM_keyconfig_update_tag(NULL, NULL); - WM_keyconfig_update(wm); + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); } /********************************** Keymap ************************************* @@ -361,200 +353,204 @@ void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname) static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid) { - wmKeyMap *km = MEM_callocN(sizeof(struct wmKeyMap), "keymap list"); + wmKeyMap *km = MEM_callocN(sizeof(struct wmKeyMap), "keymap list"); - BLI_strncpy(km->idname, idname, KMAP_MAX_NAME); - km->spaceid = spaceid; - km->regionid = regionid; + BLI_strncpy(km->idname, idname, KMAP_MAX_NAME); + km->spaceid = spaceid; + km->regionid = regionid; - { - const char *owner_id = RNA_struct_state_owner_get(); - if (owner_id) { - BLI_strncpy(km->owner_id, owner_id, sizeof(km->owner_id)); - } - } - return km; + { + const char *owner_id = RNA_struct_state_owner_get(); + if (owner_id) { + BLI_strncpy(km->owner_id, owner_id, sizeof(km->owner_id)); + } + } + return km; } static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap) { - wmKeyMap *keymapn = MEM_dupallocN(keymap); - wmKeyMapItem *kmi, *kmin; - wmKeyMapDiffItem *kmdi, *kmdin; + wmKeyMap *keymapn = MEM_dupallocN(keymap); + wmKeyMapItem *kmi, *kmin; + wmKeyMapDiffItem *kmdi, *kmdin; - keymapn->modal_items = keymap->modal_items; - keymapn->poll = keymap->poll; - keymapn->poll_modal_item = keymap->poll_modal_item; - BLI_listbase_clear(&keymapn->items); - keymapn->flag &= ~(KEYMAP_UPDATE | KEYMAP_EXPANDED); + keymapn->modal_items = keymap->modal_items; + keymapn->poll = keymap->poll; + keymapn->poll_modal_item = keymap->poll_modal_item; + BLI_listbase_clear(&keymapn->items); + keymapn->flag &= ~(KEYMAP_UPDATE | KEYMAP_EXPANDED); - for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) { - kmdin = wm_keymap_diff_item_copy(kmdi); - BLI_addtail(&keymapn->items, kmdin); - } + for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) { + kmdin = wm_keymap_diff_item_copy(kmdi); + BLI_addtail(&keymapn->items, kmdin); + } - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { - kmin = wm_keymap_item_copy(kmi); - BLI_addtail(&keymapn->items, kmin); - } + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + kmin = wm_keymap_item_copy(kmi); + BLI_addtail(&keymapn->items, kmin); + } - return keymapn; + return keymapn; } void WM_keymap_clear(wmKeyMap *keymap) { - wmKeyMapItem *kmi; - wmKeyMapDiffItem *kmdi; + wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; - for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) { - wm_keymap_diff_item_free(kmdi); - } + for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) { + wm_keymap_diff_item_free(kmdi); + } - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { - wm_keymap_item_free(kmi); - } + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + wm_keymap_item_free(kmi); + } - BLI_freelistN(&keymap->diff_items); - BLI_freelistN(&keymap->items); + BLI_freelistN(&keymap->diff_items); + BLI_freelistN(&keymap->items); } bool WM_keymap_remove(wmKeyConfig *keyconf, wmKeyMap *keymap) { - if (BLI_findindex(&keyconf->keymaps, keymap) != -1) { + if (BLI_findindex(&keyconf->keymaps, keymap) != -1) { - WM_keymap_clear(keymap); - BLI_remlink(&keyconf->keymaps, keymap); - MEM_freeN(keymap); + WM_keymap_clear(keymap); + BLI_remlink(&keyconf->keymaps, keymap); + MEM_freeN(keymap); - return true; - } - else { - return false; - } + return true; + } + else { + return false; + } } - bool WM_keymap_poll(bContext *C, wmKeyMap *keymap) { - /* If we're tagged, only use compatible. */ - if (keymap->owner_id[0] != '\0') { - const WorkSpace *workspace = CTX_wm_workspace(C); - if (BKE_workspace_owner_id_check(workspace, keymap->owner_id) == false) { - return false; - } - } - - if (UNLIKELY(BLI_listbase_is_empty(&keymap->items))) { - /* Empty key-maps may be missing more there may be a typo in the name. - * Warn early to avoid loosing time investigating each case. */ - CLOG_WARN(WM_LOG_KEYMAPS, "empty keymap '%s'", keymap->idname); - } - - if (keymap->poll != NULL) { - return keymap->poll(C); - } - return true; -} - -static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier) -{ - kmi->type = type; - kmi->val = val; - kmi->keymodifier = keymodifier; - - if (modifier == KM_ANY) { - kmi->shift = kmi->ctrl = kmi->alt = kmi->oskey = KM_ANY; - } - else { - kmi->shift = (modifier & KM_SHIFT) ? KM_MOD_FIRST : ((modifier & KM_SHIFT2) ? KM_MOD_SECOND : false); - kmi->ctrl = (modifier & KM_CTRL) ? KM_MOD_FIRST : ((modifier & KM_CTRL2) ? KM_MOD_SECOND : false); - kmi->alt = (modifier & KM_ALT) ? KM_MOD_FIRST : ((modifier & KM_ALT2) ? KM_MOD_SECOND : false); - kmi->oskey = (modifier & KM_OSKEY) ? KM_MOD_FIRST : ((modifier & KM_OSKEY2) ? KM_MOD_SECOND : false); - } + /* If we're tagged, only use compatible. */ + if (keymap->owner_id[0] != '\0') { + const WorkSpace *workspace = CTX_wm_workspace(C); + if (BKE_workspace_owner_id_check(workspace, keymap->owner_id) == false) { + return false; + } + } + + if (UNLIKELY(BLI_listbase_is_empty(&keymap->items))) { + /* Empty key-maps may be missing more there may be a typo in the name. + * Warn early to avoid loosing time investigating each case. */ + CLOG_WARN(WM_LOG_KEYMAPS, "empty keymap '%s'", keymap->idname); + } + + if (keymap->poll != NULL) { + return keymap->poll(C); + } + return true; +} + +static void keymap_event_set( + wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier) +{ + kmi->type = type; + kmi->val = val; + kmi->keymodifier = keymodifier; + + if (modifier == KM_ANY) { + kmi->shift = kmi->ctrl = kmi->alt = kmi->oskey = KM_ANY; + } + else { + kmi->shift = (modifier & KM_SHIFT) ? KM_MOD_FIRST : + ((modifier & KM_SHIFT2) ? KM_MOD_SECOND : false); + kmi->ctrl = (modifier & KM_CTRL) ? KM_MOD_FIRST : + ((modifier & KM_CTRL2) ? KM_MOD_SECOND : false); + kmi->alt = (modifier & KM_ALT) ? KM_MOD_FIRST : ((modifier & KM_ALT2) ? KM_MOD_SECOND : false); + kmi->oskey = (modifier & KM_OSKEY) ? KM_MOD_FIRST : + ((modifier & KM_OSKEY2) ? KM_MOD_SECOND : false); + } } static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi) { - keymap->kmi_id++; - if ((keymap->flag & KEYMAP_USER) == 0) { - kmi->id = keymap->kmi_id; - } - else { - kmi->id = -keymap->kmi_id; /* User defined keymap entries have negative ids */ - } + keymap->kmi_id++; + if ((keymap->flag & KEYMAP_USER) == 0) { + kmi->id = keymap->kmi_id; + } + else { + kmi->id = -keymap->kmi_id; /* User defined keymap entries have negative ids */ + } } /* if item was added, then bail out */ -wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) +wmKeyMapItem *WM_keymap_verify_item( + wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) { - wmKeyMapItem *kmi; + wmKeyMapItem *kmi; - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (STREQLEN(kmi->idname, idname, OP_MAX_TYPENAME)) { - break; - } - } - if (kmi == NULL) { - kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry"); + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (STREQLEN(kmi->idname, idname, OP_MAX_TYPENAME)) { + break; + } + } + if (kmi == NULL) { + kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry"); - BLI_addtail(&keymap->items, kmi); - BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME); + BLI_addtail(&keymap->items, kmi); + BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME); - keymap_item_set_id(keymap, kmi); + keymap_item_set_id(keymap, kmi); - keymap_event_set(kmi, type, val, modifier, keymodifier); - wm_keymap_item_properties_set(kmi); - } - return kmi; + keymap_event_set(kmi, type, val, modifier, keymodifier); + wm_keymap_item_properties_set(kmi); + } + return kmi; } /* always add item */ -wmKeyMapItem *WM_keymap_add_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) +wmKeyMapItem *WM_keymap_add_item( + wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) { - wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry"); + wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry"); - BLI_addtail(&keymap->items, kmi); - BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME); + BLI_addtail(&keymap->items, kmi); + BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME); - keymap_event_set(kmi, type, val, modifier, keymodifier); - wm_keymap_item_properties_set(kmi); + keymap_event_set(kmi, type, val, modifier, keymodifier); + wm_keymap_item_properties_set(kmi); - keymap_item_set_id(keymap, kmi); + keymap_item_set_id(keymap, kmi); - WM_keyconfig_update_tag(keymap, kmi); + WM_keyconfig_update_tag(keymap, kmi); - return kmi; + return kmi; } -wmKeyMapItem *WM_keymap_add_item_copy( - struct wmKeyMap *keymap, wmKeyMapItem *kmi_src) +wmKeyMapItem *WM_keymap_add_item_copy(struct wmKeyMap *keymap, wmKeyMapItem *kmi_src) { - wmKeyMapItem *kmi_dst = wm_keymap_item_copy(kmi_src); + wmKeyMapItem *kmi_dst = wm_keymap_item_copy(kmi_src); - BLI_addtail(&keymap->items, kmi_dst); + BLI_addtail(&keymap->items, kmi_dst); - keymap_item_set_id(keymap, kmi_dst); + keymap_item_set_id(keymap, kmi_dst); - WM_keyconfig_update_tag(keymap, kmi_dst); + WM_keyconfig_update_tag(keymap, kmi_dst); - return kmi_dst; + return kmi_dst; } bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) { - if (BLI_findindex(&keymap->items, kmi) != -1) { - if (kmi->ptr) { - WM_operator_properties_free(kmi->ptr); - MEM_freeN(kmi->ptr); - } - BLI_freelinkN(&keymap->items, kmi); + if (BLI_findindex(&keymap->items, kmi) != -1) { + if (kmi->ptr) { + WM_operator_properties_free(kmi->ptr); + MEM_freeN(kmi->ptr); + } + BLI_freelinkN(&keymap->items, kmi); - WM_keyconfig_update_tag(keymap, NULL); - return true; - } - else { - return false; - } + WM_keyconfig_update_tag(keymap, NULL); + return true; + } + else { + return false; + } } /************************** Keymap Diff and Patch **************************** @@ -565,254 +561,261 @@ bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap) { - wmKeyMapItem *kmi, *kmin; + wmKeyMapItem *kmi, *kmin; - for (kmi = addonmap->items.first; kmi; kmi = kmi->next) { - kmin = wm_keymap_item_copy(kmi); - keymap_item_set_id(keymap, kmin); - BLI_addhead(&keymap->items, kmin); - } + for (kmi = addonmap->items.first; kmi; kmi = kmi->next) { + kmin = wm_keymap_item_copy(kmi); + keymap_item_set_id(keymap, kmin); + BLI_addhead(&keymap->items, kmin); + } } static wmKeyMapItem *wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *needle) { - wmKeyMapItem *kmi; + wmKeyMapItem *kmi; - for (kmi = km->items.first; kmi; kmi = kmi->next) { - if (wm_keymap_item_equals(kmi, needle)) { - return kmi; - } - } + for (kmi = km->items.first; kmi; kmi = kmi->next) { + if (wm_keymap_item_equals(kmi, needle)) { + return kmi; + } + } - return NULL; + return NULL; } static wmKeyMapItem *wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapItem *needle) { - wmKeyMapItem *kmi; - - for (kmi = km->items.first; kmi; kmi = kmi->next) { - if (wm_keymap_item_equals_result(kmi, needle)) { - return kmi; - } - } - - return NULL; -} - -static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km) -{ - wmKeyMapItem *kmi, *to_kmi, *orig_kmi; - wmKeyMapDiffItem *kmdi; - - for (kmi = from_km->items.first; kmi; kmi = kmi->next) { - to_kmi = WM_keymap_item_find_id(to_km, kmi->id); - - if (!to_kmi) { - /* remove item */ - kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); - kmdi->remove_item = wm_keymap_item_copy(kmi); - BLI_addtail(&diff_km->diff_items, kmdi); - } - else if (to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) { - /* replace item */ - kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); - kmdi->remove_item = wm_keymap_item_copy(kmi); - kmdi->add_item = wm_keymap_item_copy(to_kmi); - BLI_addtail(&diff_km->diff_items, kmdi); - } - - /* sync expanded flag back to original so we don't loose it on repatch */ - if (to_kmi) { - orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id); - - if (!orig_kmi && addon_km) { - orig_kmi = wm_keymap_find_item_equals(addon_km, kmi); - } - - if (orig_kmi) { - orig_kmi->flag &= ~KMI_EXPANDED; - orig_kmi->flag |= (to_kmi->flag & KMI_EXPANDED); - } - } - } - - for (kmi = to_km->items.first; kmi; kmi = kmi->next) { - if (kmi->id < 0) { - /* add item */ - kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); - kmdi->add_item = wm_keymap_item_copy(kmi); - BLI_addtail(&diff_km->diff_items, kmdi); - } - } + wmKeyMapItem *kmi; + + for (kmi = km->items.first; kmi; kmi = kmi->next) { + if (wm_keymap_item_equals_result(kmi, needle)) { + return kmi; + } + } + + return NULL; +} + +static void wm_keymap_diff( + wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km) +{ + wmKeyMapItem *kmi, *to_kmi, *orig_kmi; + wmKeyMapDiffItem *kmdi; + + for (kmi = from_km->items.first; kmi; kmi = kmi->next) { + to_kmi = WM_keymap_item_find_id(to_km, kmi->id); + + if (!to_kmi) { + /* remove item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->remove_item = wm_keymap_item_copy(kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + else if (to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) { + /* replace item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->remove_item = wm_keymap_item_copy(kmi); + kmdi->add_item = wm_keymap_item_copy(to_kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + + /* sync expanded flag back to original so we don't loose it on repatch */ + if (to_kmi) { + orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id); + + if (!orig_kmi && addon_km) { + orig_kmi = wm_keymap_find_item_equals(addon_km, kmi); + } + + if (orig_kmi) { + orig_kmi->flag &= ~KMI_EXPANDED; + orig_kmi->flag |= (to_kmi->flag & KMI_EXPANDED); + } + } + } + + for (kmi = to_km->items.first; kmi; kmi = kmi->next) { + if (kmi->id < 0) { + /* add item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->add_item = wm_keymap_item_copy(kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + } } static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km) { - wmKeyMapDiffItem *kmdi; - wmKeyMapItem *kmi_remove, *kmi_add; - - for (kmdi = diff_km->diff_items.first; kmdi; kmdi = kmdi->next) { - /* find item to remove */ - kmi_remove = NULL; - if (kmdi->remove_item) { - kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item); - if (!kmi_remove) { - kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item); - } - } - - /* add item */ - if (kmdi->add_item) { - /* Do not re-add an already existing keymap item! See T42088. */ - /* We seek only for exact copy here! See T42137. */ - kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item); - - /* If kmi_add is same as kmi_remove (can happen in some cases, typically when we got kmi_remove - * from wm_keymap_find_item_equals_result()), no need to add or remove anything, see T45579. */ - /* Note: This typically happens when we apply user-defined keymap diff to a base one that was exported - * with that customized keymap already. In that case: - * - wm_keymap_find_item_equals(km, kmdi->remove_item) finds nothing (because actual shortcut of - * current base does not match kmdi->remove_item any more). - * - wm_keymap_find_item_equals_result(km, kmdi->remove_item) finds the current kmi from - * base keymap (because it does exactly the same thing). - * - wm_keymap_find_item_equals(km, kmdi->add_item) finds the same kmi, since base keymap was - * exported with that user-defined shortcut already! - * Maybe we should rather keep user-defined keymaps specific to a given base one? */ - if (kmi_add != NULL && kmi_add == kmi_remove) { - kmi_remove = NULL; - } - /* only if nothing to remove or item to remove found */ - else if (!kmi_add && (!kmdi->remove_item || kmi_remove)) { - kmi_add = wm_keymap_item_copy(kmdi->add_item); - kmi_add->flag |= KMI_USER_MODIFIED; - - if (kmi_remove) { - kmi_add->flag &= ~KMI_EXPANDED; - kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED); - kmi_add->id = kmi_remove->id; - BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add); - } - else { - keymap_item_set_id(km, kmi_add); - BLI_addtail(&km->items, kmi_add); - } - } - } - - /* remove item */ - if (kmi_remove) { - wm_keymap_item_free(kmi_remove); - BLI_freelinkN(&km->items, kmi_remove); - } - } -} - -static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap) -{ - wmKeyMap *km; - int expanded = 0; - - /* remove previous keymap in list, we will replace it */ - km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid); - if (km) { - expanded = (km->flag & (KEYMAP_EXPANDED | KEYMAP_CHILDREN_EXPANDED)); - WM_keymap_clear(km); - BLI_freelinkN(lb, km); - } - - /* copy new keymap from an existing one */ - if (usermap && !(usermap->flag & KEYMAP_DIFF)) { - /* for compatibility with old user preferences with non-diff - * keymaps we override the original entirely */ - wmKeyMapItem *kmi, *orig_kmi; - - km = wm_keymap_copy(usermap); - - /* try to find corresponding id's for items */ - for (kmi = km->items.first; kmi; kmi = kmi->next) { - orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi); - if (!orig_kmi) { - orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi); - } - - if (orig_kmi) { - kmi->id = orig_kmi->id; - } - else { - kmi->id = -(km->kmi_id++); - } - } - - km->flag |= KEYMAP_UPDATE; /* update again to create diff */ - } - else { - km = wm_keymap_copy(defaultmap); - } - - /* add addon keymap items */ - if (addonmap) { - wm_keymap_addon_add(km, addonmap); - } - - /* tag as being user edited */ - if (usermap) { - km->flag |= KEYMAP_USER_MODIFIED; - } - km->flag |= KEYMAP_USER | expanded; - - /* apply user changes of diff keymap */ - if (usermap && (usermap->flag & KEYMAP_DIFF)) { - wm_keymap_patch(km, usermap); - } - - /* add to list */ - BLI_addtail(lb, km); - - return km; -} - -static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *km) -{ - wmKeyMap *diffmap, *prevmap, *origmap; - - /* create temporary default + addon keymap for diff */ - origmap = defaultmap; - - if (addonmap) { - defaultmap = wm_keymap_copy(defaultmap); - wm_keymap_addon_add(defaultmap, addonmap); - } - - /* remove previous diff keymap in list, we will replace it */ - prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid); - if (prevmap) { - WM_keymap_clear(prevmap); - BLI_freelinkN(lb, prevmap); - } - - /* create diff keymap */ - diffmap = wm_keymap_new(km->idname, km->spaceid, km->regionid); - diffmap->flag |= KEYMAP_DIFF; - if (defaultmap->flag & KEYMAP_MODAL) { - diffmap->flag |= KEYMAP_MODAL; - } - wm_keymap_diff(diffmap, defaultmap, km, origmap, addonmap); - - /* add to list if not empty */ - if (diffmap->diff_items.first) { - BLI_addtail(lb, diffmap); - } - else { - WM_keymap_clear(diffmap); - MEM_freeN(diffmap); - } - - /* free temporary default map */ - if (addonmap) { - WM_keymap_clear(defaultmap); - MEM_freeN(defaultmap); - } + wmKeyMapDiffItem *kmdi; + wmKeyMapItem *kmi_remove, *kmi_add; + + for (kmdi = diff_km->diff_items.first; kmdi; kmdi = kmdi->next) { + /* find item to remove */ + kmi_remove = NULL; + if (kmdi->remove_item) { + kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item); + if (!kmi_remove) { + kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item); + } + } + + /* add item */ + if (kmdi->add_item) { + /* Do not re-add an already existing keymap item! See T42088. */ + /* We seek only for exact copy here! See T42137. */ + kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item); + + /* If kmi_add is same as kmi_remove (can happen in some cases, typically when we got kmi_remove + * from wm_keymap_find_item_equals_result()), no need to add or remove anything, see T45579. */ + /* Note: This typically happens when we apply user-defined keymap diff to a base one that was exported + * with that customized keymap already. In that case: + * - wm_keymap_find_item_equals(km, kmdi->remove_item) finds nothing (because actual shortcut of + * current base does not match kmdi->remove_item any more). + * - wm_keymap_find_item_equals_result(km, kmdi->remove_item) finds the current kmi from + * base keymap (because it does exactly the same thing). + * - wm_keymap_find_item_equals(km, kmdi->add_item) finds the same kmi, since base keymap was + * exported with that user-defined shortcut already! + * Maybe we should rather keep user-defined keymaps specific to a given base one? */ + if (kmi_add != NULL && kmi_add == kmi_remove) { + kmi_remove = NULL; + } + /* only if nothing to remove or item to remove found */ + else if (!kmi_add && (!kmdi->remove_item || kmi_remove)) { + kmi_add = wm_keymap_item_copy(kmdi->add_item); + kmi_add->flag |= KMI_USER_MODIFIED; + + if (kmi_remove) { + kmi_add->flag &= ~KMI_EXPANDED; + kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED); + kmi_add->id = kmi_remove->id; + BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add); + } + else { + keymap_item_set_id(km, kmi_add); + BLI_addtail(&km->items, kmi_add); + } + } + } + + /* remove item */ + if (kmi_remove) { + wm_keymap_item_free(kmi_remove); + BLI_freelinkN(&km->items, kmi_remove); + } + } +} + +static wmKeyMap *wm_keymap_patch_update(ListBase *lb, + wmKeyMap *defaultmap, + wmKeyMap *addonmap, + wmKeyMap *usermap) +{ + wmKeyMap *km; + int expanded = 0; + + /* remove previous keymap in list, we will replace it */ + km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid); + if (km) { + expanded = (km->flag & (KEYMAP_EXPANDED | KEYMAP_CHILDREN_EXPANDED)); + WM_keymap_clear(km); + BLI_freelinkN(lb, km); + } + + /* copy new keymap from an existing one */ + if (usermap && !(usermap->flag & KEYMAP_DIFF)) { + /* for compatibility with old user preferences with non-diff + * keymaps we override the original entirely */ + wmKeyMapItem *kmi, *orig_kmi; + + km = wm_keymap_copy(usermap); + + /* try to find corresponding id's for items */ + for (kmi = km->items.first; kmi; kmi = kmi->next) { + orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi); + if (!orig_kmi) { + orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi); + } + + if (orig_kmi) { + kmi->id = orig_kmi->id; + } + else { + kmi->id = -(km->kmi_id++); + } + } + + km->flag |= KEYMAP_UPDATE; /* update again to create diff */ + } + else { + km = wm_keymap_copy(defaultmap); + } + + /* add addon keymap items */ + if (addonmap) { + wm_keymap_addon_add(km, addonmap); + } + + /* tag as being user edited */ + if (usermap) { + km->flag |= KEYMAP_USER_MODIFIED; + } + km->flag |= KEYMAP_USER | expanded; + + /* apply user changes of diff keymap */ + if (usermap && (usermap->flag & KEYMAP_DIFF)) { + wm_keymap_patch(km, usermap); + } + + /* add to list */ + BLI_addtail(lb, km); + + return km; +} + +static void wm_keymap_diff_update(ListBase *lb, + wmKeyMap *defaultmap, + wmKeyMap *addonmap, + wmKeyMap *km) +{ + wmKeyMap *diffmap, *prevmap, *origmap; + + /* create temporary default + addon keymap for diff */ + origmap = defaultmap; + + if (addonmap) { + defaultmap = wm_keymap_copy(defaultmap); + wm_keymap_addon_add(defaultmap, addonmap); + } + + /* remove previous diff keymap in list, we will replace it */ + prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid); + if (prevmap) { + WM_keymap_clear(prevmap); + BLI_freelinkN(lb, prevmap); + } + + /* create diff keymap */ + diffmap = wm_keymap_new(km->idname, km->spaceid, km->regionid); + diffmap->flag |= KEYMAP_DIFF; + if (defaultmap->flag & KEYMAP_MODAL) { + diffmap->flag |= KEYMAP_MODAL; + } + wm_keymap_diff(diffmap, defaultmap, km, origmap, addonmap); + + /* add to list if not empty */ + if (diffmap->diff_items.first) { + BLI_addtail(lb, diffmap); + } + else { + WM_keymap_clear(diffmap); + MEM_freeN(diffmap); + } + + /* free temporary default map */ + if (addonmap) { + WM_keymap_clear(defaultmap); + MEM_freeN(defaultmap); + } } /* ****************** storage in WM ************ */ @@ -823,745 +826,812 @@ static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap * wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid) { - wmKeyMap *km; + wmKeyMap *km; - for (km = lb->first; km; km = km->next) { - if (km->spaceid == spaceid && km->regionid == regionid) { - if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { - return km; - } - } - } + for (km = lb->first; km; km = km->next) { + if (km->spaceid == spaceid && km->regionid == regionid) { + if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { + return km; + } + } + } - return NULL; + return NULL; } -wmKeyMap *WM_keymap_list_find_spaceid_or_empty(ListBase *lb, const char *idname, int spaceid, int regionid) +wmKeyMap *WM_keymap_list_find_spaceid_or_empty(ListBase *lb, + const char *idname, + int spaceid, + int regionid) { - wmKeyMap *km; + wmKeyMap *km; - for (km = lb->first; km; km = km->next) { - if (ELEM(km->spaceid, spaceid, SPACE_EMPTY) && km->regionid == regionid) { - if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { - return km; - } - } - } + for (km = lb->first; km; km = km->next) { + if (ELEM(km->spaceid, spaceid, SPACE_EMPTY) && km->regionid == regionid) { + if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { + return km; + } + } + } - return NULL; + return NULL; } wmKeyMap *WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid) { - wmKeyMap *km = WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); + wmKeyMap *km = WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); - if (km == NULL) { - km = wm_keymap_new(idname, spaceid, regionid); - BLI_addtail(&keyconf->keymaps, km); + if (km == NULL) { + km = wm_keymap_new(idname, spaceid, regionid); + BLI_addtail(&keyconf->keymaps, km); - WM_keyconfig_update_tag(km, NULL); - } + WM_keyconfig_update_tag(km, NULL); + } - return km; + return km; } wmKeyMap *WM_keymap_find_all(const bContext *C, const char *idname, int spaceid, int regionid) { - wmWindowManager *wm = CTX_wm_manager(C); + wmWindowManager *wm = CTX_wm_manager(C); - return WM_keymap_list_find(&wm->userconf->keymaps, idname, spaceid, regionid); + return WM_keymap_list_find(&wm->userconf->keymaps, idname, spaceid, regionid); } -wmKeyMap *WM_keymap_find_all_spaceid_or_empty(const bContext *C, const char *idname, int spaceid, int regionid) +wmKeyMap *WM_keymap_find_all_spaceid_or_empty(const bContext *C, + const char *idname, + int spaceid, + int regionid) { - wmWindowManager *wm = CTX_wm_manager(C); + wmWindowManager *wm = CTX_wm_manager(C); - return WM_keymap_list_find_spaceid_or_empty(&wm->userconf->keymaps, idname, spaceid, regionid); + return WM_keymap_list_find_spaceid_or_empty(&wm->userconf->keymaps, idname, spaceid, regionid); } /* ****************** modal keymaps ************ */ /* modal maps get linked to a running operator, and filter the keys before sending to modal() callback */ -wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items) +wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, + const char *idname, + const EnumPropertyItem *items) { - wmKeyMap *km = WM_keymap_ensure(keyconf, idname, 0, 0); - km->flag |= KEYMAP_MODAL; + wmKeyMap *km = WM_keymap_ensure(keyconf, idname, 0, 0); + km->flag |= KEYMAP_MODAL; - /* init modal items from default config */ - wmWindowManager *wm = G_MAIN->wm.first; - if (wm->defaultconf && wm->defaultconf != keyconf) { - wmKeyMap *defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0); + /* init modal items from default config */ + wmWindowManager *wm = G_MAIN->wm.first; + if (wm->defaultconf && wm->defaultconf != keyconf) { + wmKeyMap *defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0); - if (defaultkm) { - km->modal_items = defaultkm->modal_items; - km->poll = defaultkm->poll; - km->poll_modal_item = defaultkm->poll_modal_item; - } - } + if (defaultkm) { + km->modal_items = defaultkm->modal_items; + km->poll = defaultkm->poll; + km->poll_modal_item = defaultkm->poll_modal_item; + } + } - if (items) { - km->modal_items = items; - } + if (items) { + km->modal_items = items; + } - return km; + return km; } wmKeyMap *WM_modalkeymap_get(wmKeyConfig *keyconf, const char *idname) { - wmKeyMap *km; + wmKeyMap *km; - for (km = keyconf->keymaps.first; km; km = km->next) { - if (km->flag & KEYMAP_MODAL) { - if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { - break; - } - } - } + for (km = keyconf->keymaps.first; km; km = km->next) { + if (km->flag & KEYMAP_MODAL) { + if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { + break; + } + } + } - return km; + return km; } - -wmKeyMapItem *WM_modalkeymap_add_item(wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value) +wmKeyMapItem *WM_modalkeymap_add_item( + wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value) { - wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry"); + wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry"); - BLI_addtail(&km->items, kmi); - kmi->propvalue = value; + BLI_addtail(&km->items, kmi); + kmi->propvalue = value; - keymap_event_set(kmi, type, val, modifier, keymodifier); + keymap_event_set(kmi, type, val, modifier, keymodifier); - keymap_item_set_id(km, kmi); + keymap_item_set_id(km, kmi); - WM_keyconfig_update_tag(km, kmi); + WM_keyconfig_update_tag(km, kmi); - return kmi; + return kmi; } -wmKeyMapItem *WM_modalkeymap_add_item_str(wmKeyMap *km, int type, int val, int modifier, int keymodifier, const char *value) +wmKeyMapItem *WM_modalkeymap_add_item_str( + wmKeyMap *km, int type, int val, int modifier, int keymodifier, const char *value) { - wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry"); + wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry"); - BLI_addtail(&km->items, kmi); - BLI_strncpy(kmi->propvalue_str, value, sizeof(kmi->propvalue_str)); + BLI_addtail(&km->items, kmi); + BLI_strncpy(kmi->propvalue_str, value, sizeof(kmi->propvalue_str)); - keymap_event_set(kmi, type, val, modifier, keymodifier); + keymap_event_set(kmi, type, val, modifier, keymodifier); - keymap_item_set_id(km, kmi); + keymap_item_set_id(km, kmi); - WM_keyconfig_update_tag(km, kmi); + WM_keyconfig_update_tag(km, kmi); - return kmi; + return kmi; } -static wmKeyMapItem *wm_modalkeymap_find_propvalue_iter(wmKeyMap *km, wmKeyMapItem *kmi, const int propvalue) +static wmKeyMapItem *wm_modalkeymap_find_propvalue_iter(wmKeyMap *km, + wmKeyMapItem *kmi, + const int propvalue) { - if (km->flag & KEYMAP_MODAL) { - kmi = kmi ? kmi->next : km->items.first; - for (; kmi; kmi = kmi->next) { - if (kmi->propvalue == propvalue) { - return kmi; - } - } - } - else { - BLI_assert(!"called with non modal keymap"); - } + if (km->flag & KEYMAP_MODAL) { + kmi = kmi ? kmi->next : km->items.first; + for (; kmi; kmi = kmi->next) { + if (kmi->propvalue == propvalue) { + return kmi; + } + } + } + else { + BLI_assert(!"called with non modal keymap"); + } - return NULL; + return NULL; } wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue) { - return wm_modalkeymap_find_propvalue_iter(km, NULL, propvalue); + return wm_modalkeymap_find_propvalue_iter(km, NULL, propvalue); } void WM_modalkeymap_assign(wmKeyMap *km, const char *opname) { - wmOperatorType *ot = WM_operatortype_find(opname, 0); + wmOperatorType *ot = WM_operatortype_find(opname, 0); - if (ot) { - ot->modalkeymap = km; - } - else { - CLOG_ERROR(WM_LOG_KEYMAPS, "unknown operator '%s'", opname); - } + if (ot) { + ot->modalkeymap = km; + } + else { + CLOG_ERROR(WM_LOG_KEYMAPS, "unknown operator '%s'", opname); + } } static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km) { - /* here we convert propvalue string values delayed, due to python keymaps - * being created before the actual modal keymaps, so no modal_items */ - wmKeyMap *defaultkm; - wmKeyMapItem *kmi; - int propvalue; + /* here we convert propvalue string values delayed, due to python keymaps + * being created before the actual modal keymaps, so no modal_items */ + wmKeyMap *defaultkm; + wmKeyMapItem *kmi; + int propvalue; - if (km && (km->flag & KEYMAP_MODAL) && !km->modal_items) { - if (wm->defaultconf == NULL) { - return; - } + if (km && (km->flag & KEYMAP_MODAL) && !km->modal_items) { + if (wm->defaultconf == NULL) { + return; + } - defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0); + defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0); - if (!defaultkm) { - return; - } + if (!defaultkm) { + return; + } - km->modal_items = defaultkm->modal_items; - km->poll = defaultkm->poll; - km->poll_modal_item = defaultkm->poll_modal_item; + km->modal_items = defaultkm->modal_items; + km->poll = defaultkm->poll; + km->poll_modal_item = defaultkm->poll_modal_item; - if (km->modal_items) { - for (kmi = km->items.first; kmi; kmi = kmi->next) { - if (kmi->propvalue_str[0]) { - if (RNA_enum_value_from_id(km->modal_items, kmi->propvalue_str, &propvalue)) { - kmi->propvalue = propvalue; - } - kmi->propvalue_str[0] = '\0'; - } - } - } - } + if (km->modal_items) { + for (kmi = km->items.first; kmi; kmi = kmi->next) { + if (kmi->propvalue_str[0]) { + if (RNA_enum_value_from_id(km->modal_items, kmi->propvalue_str, &propvalue)) { + kmi->propvalue = propvalue; + } + kmi->propvalue_str[0] = '\0'; + } + } + } + } } /* ***************** get string from key events **************** */ const char *WM_key_event_string(const short type, const bool compact) { - const EnumPropertyItem *it; - const int i = RNA_enum_from_value(rna_enum_event_type_items, (int)type); + const EnumPropertyItem *it; + const int i = RNA_enum_from_value(rna_enum_event_type_items, (int)type); - if (i == -1) { - return ""; - } - it = &rna_enum_event_type_items[i]; + if (i == -1) { + return ""; + } + it = &rna_enum_event_type_items[i]; - /* We first try enum items' description (abused as shortname here), and fall back to usual name if empty. */ - if (compact && it->description[0]) { - /* XXX No context for enum descriptions... In practice shall not be an issue though. */ - return IFACE_(it->description); - } + /* We first try enum items' description (abused as shortname here), and fall back to usual name if empty. */ + if (compact && it->description[0]) { + /* XXX No context for enum descriptions... In practice shall not be an issue though. */ + return IFACE_(it->description); + } - return CTX_IFACE_(BLT_I18NCONTEXT_UI_EVENTS, it->name); + return CTX_IFACE_(BLT_I18NCONTEXT_UI_EVENTS, it->name); } /* TODO: also support (some) value, like e.g. double-click? */ -int WM_keymap_item_raw_to_string( - const short shift, const short ctrl, const short alt, const short oskey, - const short keymodifier, const short val, const short type, const bool compact, - char *result, const int result_len) -{ -#define ADD_SEP if (p != buf) *p++ = ' '; (void)0 - - char buf[128]; - char *p = buf; - - buf[0] = '\0'; - - /* TODO: support order (KM_SHIFT vs. KM_SHIFT2) ? */ - if (shift == KM_ANY && - ctrl == KM_ANY && - alt == KM_ANY && - oskey == KM_ANY) - { - /* Don't show anything for any mapping. */ - } - else { - if (shift) { - ADD_SEP; - p += BLI_strcpy_rlen(p, IFACE_("Shift")); - } - - if (ctrl) { - ADD_SEP; - p += BLI_strcpy_rlen(p, IFACE_("Ctrl")); - } - - if (alt) { - ADD_SEP; - p += BLI_strcpy_rlen(p, IFACE_("Alt")); - } - - if (oskey) { - ADD_SEP; - p += BLI_strcpy_rlen(p, IFACE_("Cmd")); - } - } - - if (keymodifier) { - ADD_SEP; - p += BLI_strcpy_rlen(p, WM_key_event_string(keymodifier, compact)); - } - - if (type) { - ADD_SEP; - if (val == KM_DBL_CLICK) { - p += BLI_strcpy_rlen(p, IFACE_("dbl-")); - } - p += BLI_strcpy_rlen(p, WM_key_event_string(type, compact)); - } - - /* We assume size of buf is enough to always store any possible shortcut, but let's add a debug check about it! */ - BLI_assert(p - buf < sizeof(buf)); - - /* We need utf8 here, otherwise we may 'cut' some unicode chars like arrows... */ - return BLI_strncpy_utf8_rlen(result, buf, result_len); +int WM_keymap_item_raw_to_string(const short shift, + const short ctrl, + const short alt, + const short oskey, + const short keymodifier, + const short val, + const short type, + const bool compact, + char *result, + const int result_len) +{ +#define ADD_SEP \ + if (p != buf) \ + *p++ = ' '; \ + (void)0 + + char buf[128]; + char *p = buf; + + buf[0] = '\0'; + + /* TODO: support order (KM_SHIFT vs. KM_SHIFT2) ? */ + if (shift == KM_ANY && ctrl == KM_ANY && alt == KM_ANY && oskey == KM_ANY) { + /* Don't show anything for any mapping. */ + } + else { + if (shift) { + ADD_SEP; + p += BLI_strcpy_rlen(p, IFACE_("Shift")); + } + + if (ctrl) { + ADD_SEP; + p += BLI_strcpy_rlen(p, IFACE_("Ctrl")); + } + + if (alt) { + ADD_SEP; + p += BLI_strcpy_rlen(p, IFACE_("Alt")); + } + + if (oskey) { + ADD_SEP; + p += BLI_strcpy_rlen(p, IFACE_("Cmd")); + } + } + + if (keymodifier) { + ADD_SEP; + p += BLI_strcpy_rlen(p, WM_key_event_string(keymodifier, compact)); + } + + if (type) { + ADD_SEP; + if (val == KM_DBL_CLICK) { + p += BLI_strcpy_rlen(p, IFACE_("dbl-")); + } + p += BLI_strcpy_rlen(p, WM_key_event_string(type, compact)); + } + + /* We assume size of buf is enough to always store any possible shortcut, but let's add a debug check about it! */ + BLI_assert(p - buf < sizeof(buf)); + + /* We need utf8 here, otherwise we may 'cut' some unicode chars like arrows... */ + return BLI_strncpy_utf8_rlen(result, buf, result_len); #undef ADD_SEP } -int WM_keymap_item_to_string( - wmKeyMapItem *kmi, const bool compact, - char *result, const int result_len) +int WM_keymap_item_to_string(wmKeyMapItem *kmi, + const bool compact, + char *result, + const int result_len) { - return WM_keymap_item_raw_to_string( - kmi->shift, kmi->ctrl, kmi->alt, kmi->oskey, kmi->keymodifier, kmi->val, kmi->type, - compact, result, result_len); + return WM_keymap_item_raw_to_string(kmi->shift, + kmi->ctrl, + kmi->alt, + kmi->oskey, + kmi->keymodifier, + kmi->val, + kmi->type, + compact, + result, + result_len); } int WM_modalkeymap_items_to_string( - wmKeyMap *km, const int propvalue, const bool compact, - char *result, const int result_len) -{ - int totlen = 0; - bool add_sep = false; - - if (km) { - wmKeyMapItem *kmi; - - /* Find all shortcuts related to that propvalue! */ - for (kmi = WM_modalkeymap_find_propvalue(km, propvalue); - kmi && totlen < (result_len - 2); - kmi = wm_modalkeymap_find_propvalue_iter(km, kmi, propvalue)) - { - if (add_sep) { - result[totlen++] = '/'; - result[totlen] = '\0'; - } - else { - add_sep = true; - } - totlen += WM_keymap_item_to_string(kmi, compact, &result[totlen], result_len - totlen); - } - } - - return totlen; -} - -int WM_modalkeymap_operator_items_to_string( - wmOperatorType *ot, const int propvalue, const bool compact, - char *result, const int result_len) -{ - return WM_modalkeymap_items_to_string(ot->modalkeymap, propvalue, compact, result, result_len); -} - -char *WM_modalkeymap_operator_items_to_string_buf( - wmOperatorType *ot, const int propvalue, const bool compact, - const int max_len, int *r_available_len, char **r_result) -{ - char *ret = *r_result; - - if (*r_available_len > 1) { - int used_len = WM_modalkeymap_operator_items_to_string( - ot, propvalue, compact, ret, min_ii(*r_available_len, max_len)) + 1; - - *r_available_len -= used_len; - *r_result += used_len; - if (*r_available_len == 0) { - (*r_result)--; /* So that *result keeps pointing on a valid char, we'll stay on it anyway. */ - } - } - else { - *ret = '\0'; - } - - return ret; -} - -static wmKeyMapItem *wm_keymap_item_find_in_keymap( - wmKeyMap *keymap, const char *opname, - IDProperty *properties, const bool is_strict, - const struct wmKeyMapItemFind_Params *params) -{ - for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { - /* skip disabled keymap items [T38447] */ - if (kmi->flag & KMI_INACTIVE) { - continue; - } - - bool kmi_match = false; - - if (STREQ(kmi->idname, opname)) { - if (properties) { - /* example of debugging keymaps */ + wmKeyMap *km, const int propvalue, const bool compact, char *result, const int result_len) +{ + int totlen = 0; + bool add_sep = false; + + if (km) { + wmKeyMapItem *kmi; + + /* Find all shortcuts related to that propvalue! */ + for (kmi = WM_modalkeymap_find_propvalue(km, propvalue); kmi && totlen < (result_len - 2); + kmi = wm_modalkeymap_find_propvalue_iter(km, kmi, propvalue)) { + if (add_sep) { + result[totlen++] = '/'; + result[totlen] = '\0'; + } + else { + add_sep = true; + } + totlen += WM_keymap_item_to_string(kmi, compact, &result[totlen], result_len - totlen); + } + } + + return totlen; +} + +int WM_modalkeymap_operator_items_to_string(wmOperatorType *ot, + const int propvalue, + const bool compact, + char *result, + const int result_len) +{ + return WM_modalkeymap_items_to_string(ot->modalkeymap, propvalue, compact, result, result_len); +} + +char *WM_modalkeymap_operator_items_to_string_buf(wmOperatorType *ot, + const int propvalue, + const bool compact, + const int max_len, + int *r_available_len, + char **r_result) +{ + char *ret = *r_result; + + if (*r_available_len > 1) { + int used_len = WM_modalkeymap_operator_items_to_string( + ot, propvalue, compact, ret, min_ii(*r_available_len, max_len)) + + 1; + + *r_available_len -= used_len; + *r_result += used_len; + if (*r_available_len == 0) { + (*r_result)--; /* So that *result keeps pointing on a valid char, we'll stay on it anyway. */ + } + } + else { + *ret = '\0'; + } + + return ret; +} + +static wmKeyMapItem *wm_keymap_item_find_in_keymap(wmKeyMap *keymap, + const char *opname, + IDProperty *properties, + const bool is_strict, + const struct wmKeyMapItemFind_Params *params) +{ + for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + /* skip disabled keymap items [T38447] */ + if (kmi->flag & KMI_INACTIVE) { + continue; + } + + bool kmi_match = false; + + if (STREQ(kmi->idname, opname)) { + if (properties) { + /* example of debugging keymaps */ #if 0 - if (kmi->ptr) { - if (STREQ("MESH_OT_rip_move", opname)) { - printf("OPERATOR\n"); - IDP_print(properties); - printf("KEYMAP\n"); - IDP_print(kmi->ptr->data); - } - } + if (kmi->ptr) { + if (STREQ("MESH_OT_rip_move", opname)) { + printf("OPERATOR\n"); + IDP_print(properties); + printf("KEYMAP\n"); + IDP_print(kmi->ptr->data); + } + } #endif - if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) { - kmi_match = true; - } - /* Debug only, helps spotting mismatches between menu entries and shortcuts! */ - else if (G.debug & G_DEBUG_WM) { - if (is_strict && kmi->ptr) { - wmOperatorType *ot = WM_operatortype_find(opname, true); - if (ot) { - /* make a copy of the properties and set unset ones to their default values. */ - PointerRNA opptr; - IDProperty *properties_default = IDP_CopyProperty(kmi->ptr->data); - - RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); - WM_operator_properties_default(&opptr, true); - - if (IDP_EqualsProperties_ex(properties, properties_default, is_strict)) { - char kmi_str[128]; - WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str)); - /* Note gievn properties could come from other things than menu entry... */ - printf("%s: Some set values in menu entry match default op values, " - "this might not be desired!\n", opname); - printf("\tkm: '%s', kmi: '%s'\n", keymap->idname, kmi_str); + if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) { + kmi_match = true; + } + /* Debug only, helps spotting mismatches between menu entries and shortcuts! */ + else if (G.debug & G_DEBUG_WM) { + if (is_strict && kmi->ptr) { + wmOperatorType *ot = WM_operatortype_find(opname, true); + if (ot) { + /* make a copy of the properties and set unset ones to their default values. */ + PointerRNA opptr; + IDProperty *properties_default = IDP_CopyProperty(kmi->ptr->data); + + RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); + WM_operator_properties_default(&opptr, true); + + if (IDP_EqualsProperties_ex(properties, properties_default, is_strict)) { + char kmi_str[128]; + WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str)); + /* Note gievn properties could come from other things than menu entry... */ + printf( + "%s: Some set values in menu entry match default op values, " + "this might not be desired!\n", + opname); + printf("\tkm: '%s', kmi: '%s'\n", keymap->idname, kmi_str); #ifndef NDEBUG -#ifdef WITH_PYTHON - printf("OPERATOR\n"); - IDP_print(properties); - printf("KEYMAP\n"); - IDP_print(kmi->ptr->data); -#endif +# ifdef WITH_PYTHON + printf("OPERATOR\n"); + IDP_print(properties); + printf("KEYMAP\n"); + IDP_print(kmi->ptr->data); +# endif #endif - printf("\n"); - } - - IDP_FreeProperty(properties_default); - MEM_freeN(properties_default); - } - } - } - } - else { - kmi_match = true; - } - - if (kmi_match) { - if ((params == NULL) || params->filter_fn(keymap, kmi, params->user_data)) { - return kmi; - } - } - } - } - return NULL; -} - -static wmKeyMapItem *wm_keymap_item_find_handlers( - const bContext *C, ListBase *handlers, const char *opname, int UNUSED(opcontext), - IDProperty *properties, const bool is_strict, - const struct wmKeyMapItemFind_Params *params, - wmKeyMap **r_keymap) -{ - wmWindowManager *wm = CTX_wm_manager(C); - - /* find keymap item in handlers */ - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { - if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { - wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - if (keymap && WM_keymap_poll((bContext *)C, keymap)) { - wmKeyMapItem *kmi = wm_keymap_item_find_in_keymap( - keymap, opname, properties, is_strict, params); - if (kmi != NULL) { - if (r_keymap) { - *r_keymap = keymap; - } - return kmi; - } - } - } - } - /* ensure un-initialized keymap is never used */ - if (r_keymap) { - *r_keymap = NULL; - } - return NULL; -} - -static wmKeyMapItem *wm_keymap_item_find_props( - const bContext *C, const char *opname, int opcontext, - IDProperty *properties, const bool is_strict, - const struct wmKeyMapItemFind_Params *params, - wmKeyMap **r_keymap) -{ - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); - wmKeyMapItem *found = NULL; - - /* look into multiple handler lists to find the item */ - if (win) { - found = wm_keymap_item_find_handlers( - C, &win->modalhandlers, opname, opcontext, properties, is_strict, params, r_keymap); - if (found == NULL) { - found = wm_keymap_item_find_handlers( - C, &win->handlers, opname, opcontext, properties, is_strict, params, r_keymap); - } - } - - if (sa && found == NULL) { - found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, params, r_keymap); - } - - if (found == NULL) { - if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { - if (sa) { - if (!(ar && ar->regiontype == RGN_TYPE_WINDOW)) { - ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - } - - if (ar) { - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, params, r_keymap); - } - } - } - 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, is_strict, params, r_keymap); - } - } - 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, is_strict, params, r_keymap); - } - } - else { - if (ar) { - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, params, r_keymap); - } - } - } - - return found; -} - -static wmKeyMapItem *wm_keymap_item_find( - const bContext *C, const char *opname, int opcontext, - IDProperty *properties, bool is_strict, - const struct wmKeyMapItemFind_Params *params, - wmKeyMap **r_keymap) -{ - wmKeyMapItem *found; - - /* XXX Hack! Macro operators in menu entry have their whole props defined, which is not the case for - * relevant keymap entries. Could be good to check and harmonize this, but for now always - * compare non-strict in this case. - */ - wmOperatorType *ot = WM_operatortype_find(opname, true); - if (ot) { - is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0); - } - - found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, params, r_keymap); - - /* This block is *only* useful in one case: when op uses an enum menu in its prop member - * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle, - * since now any enum prop may be used in UI (specified by name), ot->prop is not so much used... - * Otherwise: - * * If non-strict, unset properties always match set ones in IDP_EqualsProperties_ex. - * * If strict, unset properties never match set ones in IDP_EqualsProperties_ex, - * and we do not want that to change (else we get things like T41757)! - * ...so in either case, re-running a comparison with unset props set to default is useless. - */ - if (!found && properties) { - if (ot && ot->prop) { /* XXX Shall we also check ot->prop is actually an enum? */ - /* make a copy of the properties and unset the 'ot->prop' one if set. */ - PointerRNA opptr; - IDProperty *properties_temp = IDP_CopyProperty(properties); - - RNA_pointer_create(NULL, ot->srna, properties_temp, &opptr); - - if (RNA_property_is_set(&opptr, ot->prop)) { - /* for operator that has enum menu, unset it so its value does not affect comparison result */ - RNA_property_unset(&opptr, ot->prop); - - found = wm_keymap_item_find_props(C, opname, opcontext, properties_temp, is_strict, params, r_keymap); - } - - IDP_FreeProperty(properties_temp); - MEM_freeN(properties_temp); - } - } - - /* Debug only, helps spotting mismatches between menu entries and shortcuts! */ - if (G.debug & G_DEBUG_WM) { - if (!found && is_strict && properties) { - wmKeyMap *km; - wmKeyMapItem *kmi; - if (ot) { - /* make a copy of the properties and set unset ones to their default values. */ - PointerRNA opptr; - IDProperty *properties_default = IDP_CopyProperty(properties); - - RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); - WM_operator_properties_default(&opptr, true); - - kmi = wm_keymap_item_find_props(C, opname, opcontext, properties_default, is_strict, params, &km); - if (kmi) { - char kmi_str[128]; - WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str)); - printf("%s: Some set values in keymap entry match default op values, " - "this might not be desired!\n", opname); - printf("\tkm: '%s', kmi: '%s'\n", km->idname, kmi_str); + printf("\n"); + } + + IDP_FreeProperty(properties_default); + MEM_freeN(properties_default); + } + } + } + } + else { + kmi_match = true; + } + + if (kmi_match) { + if ((params == NULL) || params->filter_fn(keymap, kmi, params->user_data)) { + return kmi; + } + } + } + } + return NULL; +} + +static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C, + ListBase *handlers, + const char *opname, + int UNUSED(opcontext), + IDProperty *properties, + const bool is_strict, + const struct wmKeyMapItemFind_Params *params, + wmKeyMap **r_keymap) +{ + wmWindowManager *wm = CTX_wm_manager(C); + + /* find keymap item in handlers */ + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { + if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { + wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; + wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); + if (keymap && WM_keymap_poll((bContext *)C, keymap)) { + wmKeyMapItem *kmi = wm_keymap_item_find_in_keymap( + keymap, opname, properties, is_strict, params); + if (kmi != NULL) { + if (r_keymap) { + *r_keymap = keymap; + } + return kmi; + } + } + } + } + /* ensure un-initialized keymap is never used */ + if (r_keymap) { + *r_keymap = NULL; + } + return NULL; +} + +static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, + const char *opname, + int opcontext, + IDProperty *properties, + const bool is_strict, + const struct wmKeyMapItemFind_Params *params, + wmKeyMap **r_keymap) +{ + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + wmKeyMapItem *found = NULL; + + /* look into multiple handler lists to find the item */ + if (win) { + found = wm_keymap_item_find_handlers( + C, &win->modalhandlers, opname, opcontext, properties, is_strict, params, r_keymap); + if (found == NULL) { + found = wm_keymap_item_find_handlers( + C, &win->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + } + } + + if (sa && found == NULL) { + found = wm_keymap_item_find_handlers( + C, &sa->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + } + + if (found == NULL) { + if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { + if (sa) { + if (!(ar && ar->regiontype == RGN_TYPE_WINDOW)) { + ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + } + + if (ar) { + found = wm_keymap_item_find_handlers( + C, &ar->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + } + } + } + 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, is_strict, params, r_keymap); + } + } + 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, is_strict, params, r_keymap); + } + } + else { + if (ar) { + found = wm_keymap_item_find_handlers( + C, &ar->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + } + } + } + + return found; +} + +static wmKeyMapItem *wm_keymap_item_find(const bContext *C, + const char *opname, + int opcontext, + IDProperty *properties, + bool is_strict, + const struct wmKeyMapItemFind_Params *params, + wmKeyMap **r_keymap) +{ + wmKeyMapItem *found; + + /* XXX Hack! Macro operators in menu entry have their whole props defined, which is not the case for + * relevant keymap entries. Could be good to check and harmonize this, but for now always + * compare non-strict in this case. + */ + wmOperatorType *ot = WM_operatortype_find(opname, true); + if (ot) { + is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0); + } + + found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, params, r_keymap); + + /* This block is *only* useful in one case: when op uses an enum menu in its prop member + * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle, + * since now any enum prop may be used in UI (specified by name), ot->prop is not so much used... + * Otherwise: + * * If non-strict, unset properties always match set ones in IDP_EqualsProperties_ex. + * * If strict, unset properties never match set ones in IDP_EqualsProperties_ex, + * and we do not want that to change (else we get things like T41757)! + * ...so in either case, re-running a comparison with unset props set to default is useless. + */ + if (!found && properties) { + if (ot && ot->prop) { /* XXX Shall we also check ot->prop is actually an enum? */ + /* make a copy of the properties and unset the 'ot->prop' one if set. */ + PointerRNA opptr; + IDProperty *properties_temp = IDP_CopyProperty(properties); + + RNA_pointer_create(NULL, ot->srna, properties_temp, &opptr); + + if (RNA_property_is_set(&opptr, ot->prop)) { + /* for operator that has enum menu, unset it so its value does not affect comparison result */ + RNA_property_unset(&opptr, ot->prop); + + found = wm_keymap_item_find_props( + C, opname, opcontext, properties_temp, is_strict, params, r_keymap); + } + + IDP_FreeProperty(properties_temp); + MEM_freeN(properties_temp); + } + } + + /* Debug only, helps spotting mismatches between menu entries and shortcuts! */ + if (G.debug & G_DEBUG_WM) { + if (!found && is_strict && properties) { + wmKeyMap *km; + wmKeyMapItem *kmi; + if (ot) { + /* make a copy of the properties and set unset ones to their default values. */ + PointerRNA opptr; + IDProperty *properties_default = IDP_CopyProperty(properties); + + RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); + WM_operator_properties_default(&opptr, true); + + kmi = wm_keymap_item_find_props( + C, opname, opcontext, properties_default, is_strict, params, &km); + if (kmi) { + char kmi_str[128]; + WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str)); + printf( + "%s: Some set values in keymap entry match default op values, " + "this might not be desired!\n", + opname); + printf("\tkm: '%s', kmi: '%s'\n", km->idname, kmi_str); #ifndef NDEBUG -#ifdef WITH_PYTHON - printf("OPERATOR\n"); - IDP_print(properties); - printf("KEYMAP\n"); - IDP_print(kmi->ptr->data); -#endif +# ifdef WITH_PYTHON + printf("OPERATOR\n"); + IDP_print(properties); + printf("KEYMAP\n"); + IDP_print(kmi->ptr->data); +# endif #endif - printf("\n"); - } + printf("\n"); + } - IDP_FreeProperty(properties_default); - MEM_freeN(properties_default); - } - } - } + IDP_FreeProperty(properties_default); + MEM_freeN(properties_default); + } + } + } - return found; + return found; } -static bool kmi_filter_is_visible(const wmKeyMap *UNUSED(km), const wmKeyMapItem *kmi, void *UNUSED(user_data)) +static bool kmi_filter_is_visible(const wmKeyMap *UNUSED(km), + const wmKeyMapItem *kmi, + void *UNUSED(user_data)) { - return ((WM_key_event_string(kmi->type, false)[0] != '\0') && - (IS_EVENT_ACTIONZONE(kmi->type) == false)); + return ((WM_key_event_string(kmi->type, false)[0] != '\0') && + (IS_EVENT_ACTIONZONE(kmi->type) == false)); } -char *WM_key_event_operator_string( - const bContext *C, const char *opname, int opcontext, - IDProperty *properties, const bool is_strict, - char *result, const int result_len) +char *WM_key_event_operator_string(const bContext *C, + const char *opname, + int opcontext, + IDProperty *properties, + const bool is_strict, + char *result, + const int result_len) { - wmKeyMapItem *kmi = wm_keymap_item_find( - C, opname, opcontext, properties, is_strict, - &(struct wmKeyMapItemFind_Params){ - .filter_fn = kmi_filter_is_visible, - .user_data = NULL, - }, - NULL); - if (kmi) { - WM_keymap_item_to_string(kmi, false, result, result_len); - return result; - } + wmKeyMapItem *kmi = wm_keymap_item_find(C, + opname, + opcontext, + properties, + is_strict, + &(struct wmKeyMapItemFind_Params){ + .filter_fn = kmi_filter_is_visible, + .user_data = NULL, + }, + NULL); + if (kmi) { + WM_keymap_item_to_string(kmi, false, result, result_len); + return result; + } - return NULL; + return NULL; } -static bool kmi_filter_is_visible_type_mask(const wmKeyMap *km, const wmKeyMapItem *kmi, void *user_data) +static bool kmi_filter_is_visible_type_mask(const wmKeyMap *km, + const wmKeyMapItem *kmi, + void *user_data) { - short *mask_pair = user_data; - return ((WM_event_type_mask_test(kmi->type, mask_pair[0]) == true) && - (WM_event_type_mask_test(kmi->type, mask_pair[1]) == false) && - kmi_filter_is_visible(km, kmi, user_data)); + short *mask_pair = user_data; + return ((WM_event_type_mask_test(kmi->type, mask_pair[0]) == true) && + (WM_event_type_mask_test(kmi->type, mask_pair[1]) == false) && + kmi_filter_is_visible(km, kmi, user_data)); } /** * \param include_mask, exclude_mask: Event types to include/exclude when looking up keys (#eEventType_Mask). */ -wmKeyMapItem *WM_key_event_operator( - const bContext *C, const char *opname, int opcontext, IDProperty *properties, - const short include_mask, const short exclude_mask, - wmKeyMap **r_keymap) -{ - short user_data_mask[2] = {include_mask, exclude_mask}; - bool use_mask = (include_mask != EVT_TYPE_MASK_ALL) || (exclude_mask != 0); - return wm_keymap_item_find( - C, opname, opcontext, properties, true, - &(struct wmKeyMapItemFind_Params){ - .filter_fn = use_mask ? kmi_filter_is_visible_type_mask : kmi_filter_is_visible, - .user_data = use_mask ? user_data_mask : NULL, - }, - r_keymap); +wmKeyMapItem *WM_key_event_operator(const bContext *C, + const char *opname, + int opcontext, + IDProperty *properties, + const short include_mask, + const short exclude_mask, + wmKeyMap **r_keymap) +{ + short user_data_mask[2] = {include_mask, exclude_mask}; + bool use_mask = (include_mask != EVT_TYPE_MASK_ALL) || (exclude_mask != 0); + return wm_keymap_item_find( + C, + opname, + opcontext, + properties, + true, + &(struct wmKeyMapItemFind_Params){ + .filter_fn = use_mask ? kmi_filter_is_visible_type_mask : kmi_filter_is_visible, + .user_data = use_mask ? user_data_mask : NULL, + }, + r_keymap); +} + +wmKeyMapItem *WM_key_event_operator_from_keymap(wmKeyMap *keymap, + const char *opname, + IDProperty *properties, + const short include_mask, + const short exclude_mask) +{ + short user_data_mask[2] = {include_mask, exclude_mask}; + bool use_mask = (include_mask != EVT_TYPE_MASK_ALL) || (exclude_mask != 0); + return wm_keymap_item_find_in_keymap( + keymap, + opname, + properties, + true, + &(struct wmKeyMapItemFind_Params){ + .filter_fn = use_mask ? kmi_filter_is_visible_type_mask : kmi_filter_is_visible, + .user_data = use_mask ? user_data_mask : NULL, + }); } -wmKeyMapItem *WM_key_event_operator_from_keymap( - wmKeyMap *keymap, const char *opname, IDProperty *properties, - const short include_mask, const short exclude_mask) -{ - short user_data_mask[2] = {include_mask, exclude_mask}; - bool use_mask = (include_mask != EVT_TYPE_MASK_ALL) || (exclude_mask != 0); - return wm_keymap_item_find_in_keymap( - keymap, opname, properties, true, - &(struct wmKeyMapItemFind_Params){ - .filter_fn = use_mask ? kmi_filter_is_visible_type_mask : kmi_filter_is_visible, - .user_data = use_mask ? user_data_mask : NULL, - }); -} - - bool WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) { - int k1type, k2type; + int k1type, k2type; - if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE) { - return 0; - } + if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE) { + return 0; + } - /* take event mapping into account */ - k1type = WM_userdef_event_map(k1->type); - k2type = WM_userdef_event_map(k2->type); + /* take event mapping into account */ + k1type = WM_userdef_event_map(k1->type); + k2type = WM_userdef_event_map(k2->type); - if (k1type != KM_ANY && k2type != KM_ANY && k1type != k2type) { - return 0; - } + if (k1type != KM_ANY && k2type != KM_ANY && k1type != k2type) { + return 0; + } - if (k1->val != KM_ANY && k2->val != KM_ANY) { - /* take click, press, release conflict into account */ - if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) { - return 0; - } - if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) { - return 0; - } - if (k1->val != k2->val) { - return 0; - } - } + if (k1->val != KM_ANY && k2->val != KM_ANY) { + /* take click, press, release conflict into account */ + if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) { + return 0; + } + if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) { + return 0; + } + if (k1->val != k2->val) { + return 0; + } + } - if (k1->shift != KM_ANY && k2->shift != KM_ANY && k1->shift != k2->shift) { - return 0; - } + if (k1->shift != KM_ANY && k2->shift != KM_ANY && k1->shift != k2->shift) { + return 0; + } - if (k1->ctrl != KM_ANY && k2->ctrl != KM_ANY && k1->ctrl != k2->ctrl) { - return 0; - } + if (k1->ctrl != KM_ANY && k2->ctrl != KM_ANY && k1->ctrl != k2->ctrl) { + return 0; + } - if (k1->alt != KM_ANY && k2->alt != KM_ANY && k1->alt != k2->alt) { - return 0; - } + if (k1->alt != KM_ANY && k2->alt != KM_ANY && k1->alt != k2->alt) { + return 0; + } - if (k1->oskey != KM_ANY && k2->oskey != KM_ANY && k1->oskey != k2->oskey) { - return 0; - } + if (k1->oskey != KM_ANY && k2->oskey != KM_ANY && k1->oskey != k2->oskey) { + return 0; + } - if (k1->keymodifier != k2->keymodifier) { - return 0; - } + if (k1->keymodifier != k2->keymodifier) { + return 0; + } - return 1; + return 1; } /************************* Update Final Configuration ************************* @@ -1571,171 +1641,170 @@ bool WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) /* so operator removal can trigger update */ enum { - WM_KEYMAP_UPDATE_RECONFIGURE = (1 << 0), + WM_KEYMAP_UPDATE_RECONFIGURE = (1 << 0), - /* ensure all wmKeyMap have their operator types validated after removing an operator */ - WM_KEYMAP_UPDATE_OPERATORTYPE = (1 << 1), + /* ensure all wmKeyMap have their operator types validated after removing an operator */ + WM_KEYMAP_UPDATE_OPERATORTYPE = (1 << 1), }; static char wm_keymap_update_flag = 0; void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi) { - /* quick tag to do delayed keymap updates */ - wm_keymap_update_flag |= WM_KEYMAP_UPDATE_RECONFIGURE; + /* quick tag to do delayed keymap updates */ + wm_keymap_update_flag |= WM_KEYMAP_UPDATE_RECONFIGURE; - if (km) { - km->flag |= KEYMAP_UPDATE; - } - if (kmi) { - kmi->flag |= KMI_UPDATE; - } + if (km) { + km->flag |= KEYMAP_UPDATE; + } + if (kmi) { + kmi->flag |= KMI_UPDATE; + } } void WM_keyconfig_update_operatortype(void) { - wm_keymap_update_flag |= WM_KEYMAP_UPDATE_OPERATORTYPE; + wm_keymap_update_flag |= WM_KEYMAP_UPDATE_OPERATORTYPE; } static bool wm_keymap_test_and_clear_update(wmKeyMap *km) { - wmKeyMapItem *kmi; - int update; + wmKeyMapItem *kmi; + int update; - update = (km->flag & KEYMAP_UPDATE); - km->flag &= ~KEYMAP_UPDATE; + update = (km->flag & KEYMAP_UPDATE); + km->flag &= ~KEYMAP_UPDATE; - for (kmi = km->items.first; kmi; kmi = kmi->next) { - update = update || (kmi->flag & KMI_UPDATE); - kmi->flag &= ~KMI_UPDATE; - } + for (kmi = km->items.first; kmi; kmi = kmi->next) { + update = update || (kmi->flag & KMI_UPDATE); + kmi->flag &= ~KMI_UPDATE; + } - return (update != 0); + return (update != 0); } static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km) { - wmKeyConfig *keyconf = WM_keyconfig_active(wm); - wmKeyMap *keymap; + wmKeyConfig *keyconf = WM_keyconfig_active(wm); + wmKeyMap *keymap; - keymap = WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid); - if (!keymap && wm->defaultconf) { - keymap = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid); - } + keymap = WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid); + if (!keymap && wm->defaultconf) { + keymap = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid); + } - return keymap; + return keymap; } void WM_keyconfig_update(wmWindowManager *wm) { - wmKeyMap *km, *defaultmap, *addonmap, *usermap, *kmn; - wmKeyMapItem *kmi; - wmKeyMapDiffItem *kmdi; - bool compat_update = false; - - if (G.background) { - return; - } - - if (wm_keymap_update_flag == 0) { - return; - } - - if (wm_keymap_update_flag & WM_KEYMAP_UPDATE_OPERATORTYPE) { - /* an operatortype has been removed, this wont happen often - * but when it does we have to check _every_ keymap item */ - wmKeyConfig *kc; - - ListBase *keymaps_lb[] = { - &U.user_keymaps, - &wm->userconf->keymaps, - &wm->defaultconf->keymaps, - &wm->addonconf->keymaps, - NULL, - }; - - int i; - - for (i = 0; keymaps_lb[i]; i++) { - wm_keyconfig_properties_update_ot(keymaps_lb[i]); - } - - for (kc = wm->keyconfigs.first; kc; kc = kc->next) { - wm_keyconfig_properties_update_ot(&kc->keymaps); - } - - wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_OPERATORTYPE; - } - - - if (wm_keymap_update_flag == 0) { - return; - } - - /* update operator properties for non-modal user keymaps */ - for (km = U.user_keymaps.first; km; km = km->next) { - if ((km->flag & KEYMAP_MODAL) == 0) { - for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { - if (kmdi->add_item) { - wm_keymap_item_properties_set(kmdi->add_item); - } - if (kmdi->remove_item) { - wm_keymap_item_properties_set(kmdi->remove_item); - } - } - - for (kmi = km->items.first; kmi; kmi = kmi->next) { - wm_keymap_item_properties_set(kmi); - } - } - } - - /* update U.user_keymaps with user key configuration changes */ - for (km = wm->userconf->keymaps.first; km; km = km->next) { - /* only diff if the user keymap was modified */ - if (wm_keymap_test_and_clear_update(km)) { - /* find keymaps */ - defaultmap = wm_keymap_preset(wm, km); - addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); - - /* diff */ - if (defaultmap) { - wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km); - } - } - } - - /* create user key configuration from preset + addon + user preferences */ - for (km = wm->defaultconf->keymaps.first; km; km = km->next) { - /* find keymaps */ - defaultmap = wm_keymap_preset(wm, km); - addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); - usermap = WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid); - - wm_user_modal_keymap_set_items(wm, defaultmap); - - /* add */ - kmn = wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap); - - if (kmn) { - kmn->modal_items = km->modal_items; - kmn->poll = km->poll; - kmn->poll_modal_item = km->poll_modal_item; - } - - /* in case of old non-diff keymaps, force extra update to create diffs */ - compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF)); - - } - - wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_RECONFIGURE; - - BLI_assert(wm_keymap_update_flag == 0); - - if (compat_update) { - WM_keyconfig_update_tag(NULL, NULL); - WM_keyconfig_update(wm); - } + wmKeyMap *km, *defaultmap, *addonmap, *usermap, *kmn; + wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; + bool compat_update = false; + + if (G.background) { + return; + } + + if (wm_keymap_update_flag == 0) { + return; + } + + if (wm_keymap_update_flag & WM_KEYMAP_UPDATE_OPERATORTYPE) { + /* an operatortype has been removed, this wont happen often + * but when it does we have to check _every_ keymap item */ + wmKeyConfig *kc; + + ListBase *keymaps_lb[] = { + &U.user_keymaps, + &wm->userconf->keymaps, + &wm->defaultconf->keymaps, + &wm->addonconf->keymaps, + NULL, + }; + + int i; + + for (i = 0; keymaps_lb[i]; i++) { + wm_keyconfig_properties_update_ot(keymaps_lb[i]); + } + + for (kc = wm->keyconfigs.first; kc; kc = kc->next) { + wm_keyconfig_properties_update_ot(&kc->keymaps); + } + + wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_OPERATORTYPE; + } + + if (wm_keymap_update_flag == 0) { + return; + } + + /* update operator properties for non-modal user keymaps */ + for (km = U.user_keymaps.first; km; km = km->next) { + if ((km->flag & KEYMAP_MODAL) == 0) { + for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { + if (kmdi->add_item) { + wm_keymap_item_properties_set(kmdi->add_item); + } + if (kmdi->remove_item) { + wm_keymap_item_properties_set(kmdi->remove_item); + } + } + + for (kmi = km->items.first; kmi; kmi = kmi->next) { + wm_keymap_item_properties_set(kmi); + } + } + } + + /* update U.user_keymaps with user key configuration changes */ + for (km = wm->userconf->keymaps.first; km; km = km->next) { + /* only diff if the user keymap was modified */ + if (wm_keymap_test_and_clear_update(km)) { + /* find keymaps */ + defaultmap = wm_keymap_preset(wm, km); + addonmap = WM_keymap_list_find( + &wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); + + /* diff */ + if (defaultmap) { + wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km); + } + } + } + + /* create user key configuration from preset + addon + user preferences */ + for (km = wm->defaultconf->keymaps.first; km; km = km->next) { + /* find keymaps */ + defaultmap = wm_keymap_preset(wm, km); + addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); + usermap = WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid); + + wm_user_modal_keymap_set_items(wm, defaultmap); + + /* add */ + kmn = wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap); + + if (kmn) { + kmn->modal_items = km->modal_items; + kmn->poll = km->poll; + kmn->poll_modal_item = km->poll_modal_item; + } + + /* in case of old non-diff keymaps, force extra update to create diffs */ + compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF)); + } + + wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_RECONFIGURE; + + BLI_assert(wm_keymap_update_flag == 0); + + if (compat_update) { + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); + } } /********************************* Event Handling ***************************** @@ -1745,20 +1814,21 @@ void WM_keyconfig_update(wmWindowManager *wm) wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) { - wmKeyMap *km; + wmKeyMap *km; - if (!keymap) { - return NULL; - } + if (!keymap) { + return NULL; + } - /* first user defined keymaps */ - km = WM_keymap_list_find(&wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + /* first user defined keymaps */ + km = WM_keymap_list_find( + &wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - if (km) { - return km; - } + if (km) { + return km; + } - return keymap; + return keymap; } /******************************* Keymap Editor ******************************** @@ -1766,95 +1836,97 @@ wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi) { - wmWindowManager *wm = CTX_wm_manager(C); - wmKeyMap *defaultmap, *addonmap; - wmKeyMapItem *orig; - - if (!keymap) { - return; - } - - /* construct default keymap from preset + addons */ - defaultmap = wm_keymap_preset(wm, keymap); - addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - - if (addonmap) { - defaultmap = wm_keymap_copy(defaultmap); - wm_keymap_addon_add(defaultmap, addonmap); - } - - /* find original item */ - orig = WM_keymap_item_find_id(defaultmap, kmi->id); - - if (orig) { - /* restore to original */ - if (!STREQ(orig->idname, kmi->idname)) { - BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname)); - WM_keymap_properties_reset(kmi, NULL); - } - - if (orig->properties) { - if (kmi->properties) { - IDP_FreeProperty(kmi->properties); - MEM_freeN(kmi->properties); - kmi->properties = NULL; - } - - kmi->properties = IDP_CopyProperty(orig->properties); - kmi->ptr->data = kmi->properties; - } - - kmi->propvalue = orig->propvalue; - kmi->type = orig->type; - kmi->val = orig->val; - kmi->shift = orig->shift; - kmi->ctrl = orig->ctrl; - kmi->alt = orig->alt; - kmi->oskey = orig->oskey; - kmi->keymodifier = orig->keymodifier; - kmi->maptype = orig->maptype; - - WM_keyconfig_update_tag(keymap, kmi); - } - - /* free temporary keymap */ - if (addonmap) { - WM_keymap_clear(defaultmap); - MEM_freeN(defaultmap); - } + wmWindowManager *wm = CTX_wm_manager(C); + wmKeyMap *defaultmap, *addonmap; + wmKeyMapItem *orig; + + if (!keymap) { + return; + } + + /* construct default keymap from preset + addons */ + defaultmap = wm_keymap_preset(wm, keymap); + addonmap = WM_keymap_list_find( + &wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + + if (addonmap) { + defaultmap = wm_keymap_copy(defaultmap); + wm_keymap_addon_add(defaultmap, addonmap); + } + + /* find original item */ + orig = WM_keymap_item_find_id(defaultmap, kmi->id); + + if (orig) { + /* restore to original */ + if (!STREQ(orig->idname, kmi->idname)) { + BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname)); + WM_keymap_properties_reset(kmi, NULL); + } + + if (orig->properties) { + if (kmi->properties) { + IDP_FreeProperty(kmi->properties); + MEM_freeN(kmi->properties); + kmi->properties = NULL; + } + + kmi->properties = IDP_CopyProperty(orig->properties); + kmi->ptr->data = kmi->properties; + } + + kmi->propvalue = orig->propvalue; + kmi->type = orig->type; + kmi->val = orig->val; + kmi->shift = orig->shift; + kmi->ctrl = orig->ctrl; + kmi->alt = orig->alt; + kmi->oskey = orig->oskey; + kmi->keymodifier = orig->keymodifier; + kmi->maptype = orig->maptype; + + WM_keyconfig_update_tag(keymap, kmi); + } + + /* free temporary keymap */ + if (addonmap) { + WM_keymap_clear(defaultmap); + MEM_freeN(defaultmap); + } } void WM_keymap_restore_to_default(wmKeyMap *keymap, bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - wmKeyMap *usermap; + wmWindowManager *wm = CTX_wm_manager(C); + wmKeyMap *usermap; - /* remove keymap from U.user_keymaps and update */ - usermap = WM_keymap_list_find(&U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + /* remove keymap from U.user_keymaps and update */ + usermap = WM_keymap_list_find( + &U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - if (usermap) { - WM_keymap_clear(usermap); - BLI_freelinkN(&U.user_keymaps, usermap); + if (usermap) { + WM_keymap_clear(usermap); + BLI_freelinkN(&U.user_keymaps, usermap); - WM_keyconfig_update_tag(NULL, NULL); - WM_keyconfig_update(wm); - } + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); + } } wmKeyMapItem *WM_keymap_item_find_id(wmKeyMap *keymap, int id) { - wmKeyMapItem *kmi; + wmKeyMapItem *kmi; - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (kmi->id == id) { - return kmi; - } - } + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (kmi->id == id) { + return kmi; + } + } - return NULL; + return NULL; } const char *WM_bool_as_string(bool test) { - return test ? IFACE_("ON") : IFACE_("OFF"); + return test ? IFACE_("ON") : IFACE_("OFF"); } diff --git a/source/blender/windowmanager/intern/wm_keymap_utils.c b/source/blender/windowmanager/intern/wm_keymap_utils.c index 7a5c0d4d2b8..37a7ed4d751 100644 --- a/source/blender/windowmanager/intern/wm_keymap_utils.c +++ b/source/blender/windowmanager/intern/wm_keymap_utils.c @@ -43,53 +43,64 @@ * \{ */ /* menu wrapper for WM_keymap_add_item */ -wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) +wmKeyMapItem *WM_keymap_add_menu( + wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) { - wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_menu", type, val, modifier, keymodifier); - RNA_string_set(kmi->ptr, "name", idname); - return kmi; + wmKeyMapItem *kmi = WM_keymap_add_item( + keymap, "WM_OT_call_menu", type, val, modifier, keymodifier); + RNA_string_set(kmi->ptr, "name", idname); + return kmi; } -wmKeyMapItem *WM_keymap_add_menu_pie(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) +wmKeyMapItem *WM_keymap_add_menu_pie( + wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) { - wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_menu_pie", type, val, modifier, keymodifier); - RNA_string_set(kmi->ptr, "name", idname); - return kmi; + wmKeyMapItem *kmi = WM_keymap_add_item( + keymap, "WM_OT_call_menu_pie", type, val, modifier, keymodifier); + RNA_string_set(kmi->ptr, "name", idname); + return kmi; } -wmKeyMapItem *WM_keymap_add_panel(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) +wmKeyMapItem *WM_keymap_add_panel( + wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) { - wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_panel", type, val, modifier, keymodifier); - RNA_string_set(kmi->ptr, "name", idname); - /* TODO: we might want to disable this. */ - RNA_boolean_set(kmi->ptr, "keep_open", false); - return kmi; + wmKeyMapItem *kmi = WM_keymap_add_item( + keymap, "WM_OT_call_panel", type, val, modifier, keymodifier); + RNA_string_set(kmi->ptr, "name", idname); + /* TODO: we might want to disable this. */ + RNA_boolean_set(kmi->ptr, "keep_open", false); + return kmi; } /* tool wrapper for WM_keymap_add_item */ -wmKeyMapItem *WM_keymap_add_tool(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) +wmKeyMapItem *WM_keymap_add_tool( + wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier) { - wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_tool_set_by_id", type, val, modifier, keymodifier); - RNA_string_set(kmi->ptr, "name", idname); - return kmi; + wmKeyMapItem *kmi = WM_keymap_add_item( + keymap, "WM_OT_tool_set_by_id", type, val, modifier, keymodifier); + RNA_string_set(kmi->ptr, "name", idname); + return kmi; } /** Useful for mapping numbers to an enum. */ -void WM_keymap_add_context_enum_set_items( - wmKeyMap *keymap, const EnumPropertyItem *items, const char *data_path, - int type_start, int val, int modifier, int keymodifier) +void WM_keymap_add_context_enum_set_items(wmKeyMap *keymap, + const EnumPropertyItem *items, + const char *data_path, + int type_start, + int val, + int modifier, + int keymodifier) { - for (int i = 0, type_offset = 0; items[i].identifier; i++) { - if (items[i].identifier[0] == '\0') { - continue; - } - wmKeyMapItem *kmi = WM_keymap_add_item( - keymap, "WM_OT_context_set_enum", - type_start + type_offset, val, modifier, keymodifier); - RNA_string_set(kmi->ptr, "data_path", data_path); - RNA_string_set(kmi->ptr, "value", items[i].identifier); - type_offset += 1; - } + for (int i = 0, type_offset = 0; items[i].identifier; i++) { + if (items[i].identifier[0] == '\0') { + continue; + } + wmKeyMapItem *kmi = WM_keymap_add_item( + keymap, "WM_OT_context_set_enum", type_start + type_offset, val, modifier, keymodifier); + RNA_string_set(kmi->ptr, "data_path", data_path); + RNA_string_set(kmi->ptr, "value", items[i].identifier); + type_offset += 1; + } } /** \} */ @@ -100,320 +111,347 @@ void WM_keymap_add_context_enum_set_items( wmKeyMap *WM_keymap_guess_from_context(const bContext *C) { - SpaceLink *sl = CTX_wm_space_data(C); - const char *km_id = NULL; - if (sl->spacetype == SPACE_VIEW3D) { - const enum eContextObjectMode mode = CTX_data_mode_enum(C); - switch (mode) { - case CTX_MODE_EDIT_MESH: km_id = "Mesh"; break; - case CTX_MODE_EDIT_CURVE: km_id = "Curve"; break; - case CTX_MODE_EDIT_SURFACE: km_id = "Curve"; break; - case CTX_MODE_EDIT_TEXT: km_id = "Font"; break; - case CTX_MODE_EDIT_ARMATURE: km_id = "Armature"; break; - case CTX_MODE_EDIT_METABALL: km_id = "Metaball"; break; - case CTX_MODE_EDIT_LATTICE: km_id = "Lattice"; break; - case CTX_MODE_POSE: km_id = "Pose"; break; - case CTX_MODE_SCULPT: km_id = "Sculpt"; break; - case CTX_MODE_PAINT_WEIGHT: km_id = "Weight Paint"; break; - case CTX_MODE_PAINT_VERTEX: km_id = "Vertex Paint"; break; - case CTX_MODE_PAINT_TEXTURE: km_id = "Image Paint"; break; - case CTX_MODE_PARTICLE: km_id = "Particle"; break; - case CTX_MODE_OBJECT: km_id = "Object Mode"; break; - case CTX_MODE_PAINT_GPENCIL: km_id = "Grease Pencil Stroke Paint Mode"; break; - case CTX_MODE_EDIT_GPENCIL: km_id = "Grease Pencil Stroke Edit Mode"; break; - case CTX_MODE_SCULPT_GPENCIL: km_id = "Grease Pencil Stroke Sculpt Mode"; break; - case CTX_MODE_WEIGHT_GPENCIL: km_id = "Grease Pencil Stroke Weight Mode"; break; - } - } - else if (sl->spacetype == SPACE_IMAGE) { - const SpaceImage *sima = (SpaceImage *)sl; - const eSpaceImage_Mode mode = sima->mode; - switch (mode) { - case SI_MODE_VIEW: km_id = "Image"; break; - case SI_MODE_PAINT: km_id = "Image Paint"; break; - case SI_MODE_MASK: km_id = "Mask Editing"; break; - case SI_MODE_UV: km_id = "UV Editor"; break; - } - } - else { - return NULL; - } + SpaceLink *sl = CTX_wm_space_data(C); + const char *km_id = NULL; + if (sl->spacetype == SPACE_VIEW3D) { + const enum eContextObjectMode mode = CTX_data_mode_enum(C); + switch (mode) { + case CTX_MODE_EDIT_MESH: + km_id = "Mesh"; + break; + case CTX_MODE_EDIT_CURVE: + km_id = "Curve"; + break; + case CTX_MODE_EDIT_SURFACE: + km_id = "Curve"; + break; + case CTX_MODE_EDIT_TEXT: + km_id = "Font"; + break; + case CTX_MODE_EDIT_ARMATURE: + km_id = "Armature"; + break; + case CTX_MODE_EDIT_METABALL: + km_id = "Metaball"; + break; + case CTX_MODE_EDIT_LATTICE: + km_id = "Lattice"; + break; + case CTX_MODE_POSE: + km_id = "Pose"; + break; + case CTX_MODE_SCULPT: + km_id = "Sculpt"; + break; + case CTX_MODE_PAINT_WEIGHT: + km_id = "Weight Paint"; + break; + case CTX_MODE_PAINT_VERTEX: + km_id = "Vertex Paint"; + break; + case CTX_MODE_PAINT_TEXTURE: + km_id = "Image Paint"; + break; + case CTX_MODE_PARTICLE: + km_id = "Particle"; + break; + case CTX_MODE_OBJECT: + km_id = "Object Mode"; + break; + case CTX_MODE_PAINT_GPENCIL: + km_id = "Grease Pencil Stroke Paint Mode"; + break; + case CTX_MODE_EDIT_GPENCIL: + km_id = "Grease Pencil Stroke Edit Mode"; + break; + case CTX_MODE_SCULPT_GPENCIL: + km_id = "Grease Pencil Stroke Sculpt Mode"; + break; + case CTX_MODE_WEIGHT_GPENCIL: + km_id = "Grease Pencil Stroke Weight Mode"; + break; + } + } + else if (sl->spacetype == SPACE_IMAGE) { + const SpaceImage *sima = (SpaceImage *)sl; + const eSpaceImage_Mode mode = sima->mode; + switch (mode) { + case SI_MODE_VIEW: + km_id = "Image"; + break; + case SI_MODE_PAINT: + km_id = "Image Paint"; + break; + case SI_MODE_MASK: + km_id = "Mask Editing"; + break; + case SI_MODE_UV: + km_id = "UV Editor"; + break; + } + } + else { + return NULL; + } - wmKeyMap *km = WM_keymap_find_all(C, km_id, 0, 0); - BLI_assert(km); - return km; + wmKeyMap *km = WM_keymap_find_all(C, km_id, 0, 0); + BLI_assert(km); + return km; } /* Guess an appropriate keymap from the operator name */ /* Needs to be kept up to date with Keymap and Operator naming */ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) { - /* Op types purposely skipped for now: - * BRUSH_OT - * BOID_OT - * BUTTONS_OT - * CONSTRAINT_OT - * PAINT_OT - * ED_OT - * FLUID_OT - * TEXTURE_OT - * UI_OT - * VIEW2D_OT - * WORLD_OT - */ + /* Op types purposely skipped for now: + * BRUSH_OT + * BOID_OT + * BUTTONS_OT + * CONSTRAINT_OT + * PAINT_OT + * ED_OT + * FLUID_OT + * TEXTURE_OT + * UI_OT + * VIEW2D_OT + * WORLD_OT + */ - wmKeyMap *km = NULL; - SpaceLink *sl = CTX_wm_space_data(C); + wmKeyMap *km = NULL; + SpaceLink *sl = CTX_wm_space_data(C); - /* Window */ - if (STRPREFIX(opname, "WM_OT") || - STRPREFIX(opname, "ED_OT_undo")) - { - if (STREQ(opname, "WM_OT_tool_set_by_id")) { - km = WM_keymap_guess_from_context(C); - } + /* Window */ + if (STRPREFIX(opname, "WM_OT") || STRPREFIX(opname, "ED_OT_undo")) { + if (STREQ(opname, "WM_OT_tool_set_by_id")) { + km = WM_keymap_guess_from_context(C); + } - if (km == NULL) { - km = WM_keymap_find_all(C, "Window", 0, 0); - } - } - /* Screen & Render */ - else if (STRPREFIX(opname, "SCREEN_OT") || - STRPREFIX(opname, "RENDER_OT") || - STRPREFIX(opname, "SOUND_OT") || - STRPREFIX(opname, "SCENE_OT")) - { - km = WM_keymap_find_all(C, "Screen", 0, 0); - } - /* Grease Pencil */ - else if (STRPREFIX(opname, "GPENCIL_OT")) { - km = WM_keymap_find_all(C, "Grease Pencil", 0, 0); - } - /* Markers */ - else if (STRPREFIX(opname, "MARKER_OT")) { - km = WM_keymap_find_all(C, "Markers", 0, 0); - } - /* Import/Export*/ - else if (STRPREFIX(opname, "IMPORT_") || - STRPREFIX(opname, "EXPORT_")) - { - km = WM_keymap_find_all(C, "Window", 0, 0); - } + if (km == NULL) { + km = WM_keymap_find_all(C, "Window", 0, 0); + } + } + /* Screen & Render */ + else if (STRPREFIX(opname, "SCREEN_OT") || STRPREFIX(opname, "RENDER_OT") || + STRPREFIX(opname, "SOUND_OT") || STRPREFIX(opname, "SCENE_OT")) { + km = WM_keymap_find_all(C, "Screen", 0, 0); + } + /* Grease Pencil */ + else if (STRPREFIX(opname, "GPENCIL_OT")) { + km = WM_keymap_find_all(C, "Grease Pencil", 0, 0); + } + /* Markers */ + else if (STRPREFIX(opname, "MARKER_OT")) { + km = WM_keymap_find_all(C, "Markers", 0, 0); + } + /* Import/Export*/ + else if (STRPREFIX(opname, "IMPORT_") || STRPREFIX(opname, "EXPORT_")) { + km = WM_keymap_find_all(C, "Window", 0, 0); + } + /* 3D View */ + else if (STRPREFIX(opname, "VIEW3D_OT")) { + km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0); + } + else if (STRPREFIX(opname, "OBJECT_OT")) { + /* exception, this needs to work outside object mode too */ + if (STRPREFIX(opname, "OBJECT_OT_mode_set")) { + km = WM_keymap_find_all(C, "Object Non-modal", 0, 0); + } + else { + km = WM_keymap_find_all(C, "Object Mode", 0, 0); + } + } + /* Object mode related */ + else if (STRPREFIX(opname, "GROUP_OT") || STRPREFIX(opname, "MATERIAL_OT") || + STRPREFIX(opname, "PTCACHE_OT") || STRPREFIX(opname, "RIGIDBODY_OT")) { + km = WM_keymap_find_all(C, "Object Mode", 0, 0); + } - /* 3D View */ - else if (STRPREFIX(opname, "VIEW3D_OT")) { - km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0); - } - else if (STRPREFIX(opname, "OBJECT_OT")) { - /* exception, this needs to work outside object mode too */ - if (STRPREFIX(opname, "OBJECT_OT_mode_set")) { - km = WM_keymap_find_all(C, "Object Non-modal", 0, 0); - } - else { - km = WM_keymap_find_all(C, "Object Mode", 0, 0); - } - } - /* Object mode related */ - else if (STRPREFIX(opname, "GROUP_OT") || - STRPREFIX(opname, "MATERIAL_OT") || - STRPREFIX(opname, "PTCACHE_OT") || - STRPREFIX(opname, "RIGIDBODY_OT")) - { - km = WM_keymap_find_all(C, "Object Mode", 0, 0); - } + /* Editing Modes */ + else if (STRPREFIX(opname, "MESH_OT")) { + km = WM_keymap_find_all(C, "Mesh", 0, 0); - /* Editing Modes */ - else if (STRPREFIX(opname, "MESH_OT")) { - km = WM_keymap_find_all(C, "Mesh", 0, 0); + /* some mesh operators are active in object mode too, like add-prim */ + if (km && !WM_keymap_poll((bContext *)C, km)) { + km = WM_keymap_find_all(C, "Object Mode", 0, 0); + } + } + else if (STRPREFIX(opname, "CURVE_OT") || STRPREFIX(opname, "SURFACE_OT")) { + km = WM_keymap_find_all(C, "Curve", 0, 0); - /* some mesh operators are active in object mode too, like add-prim */ - if (km && !WM_keymap_poll((bContext *)C, km)) { - km = WM_keymap_find_all(C, "Object Mode", 0, 0); - } - } - else if (STRPREFIX(opname, "CURVE_OT") || - STRPREFIX(opname, "SURFACE_OT")) - { - km = WM_keymap_find_all(C, "Curve", 0, 0); + /* some curve operators are active in object mode too, like add-prim */ + if (km && !WM_keymap_poll((bContext *)C, km)) { + km = WM_keymap_find_all(C, "Object Mode", 0, 0); + } + } + else if (STRPREFIX(opname, "ARMATURE_OT") || STRPREFIX(opname, "SKETCH_OT")) { + km = WM_keymap_find_all(C, "Armature", 0, 0); + } + else if (STRPREFIX(opname, "POSE_OT") || STRPREFIX(opname, "POSELIB_OT")) { + km = WM_keymap_find_all(C, "Pose", 0, 0); + } + else if (STRPREFIX(opname, "SCULPT_OT")) { + switch (CTX_data_mode_enum(C)) { + case CTX_MODE_SCULPT: + km = WM_keymap_find_all(C, "Sculpt", 0, 0); + break; + case CTX_MODE_EDIT_MESH: + km = WM_keymap_find_all(C, "UV Sculpt", 0, 0); + break; + default: + break; + } + } + else if (STRPREFIX(opname, "MBALL_OT")) { + km = WM_keymap_find_all(C, "Metaball", 0, 0); - /* some curve operators are active in object mode too, like add-prim */ - if (km && !WM_keymap_poll((bContext *)C, km)) { - km = WM_keymap_find_all(C, "Object Mode", 0, 0); - } - } - else if (STRPREFIX(opname, "ARMATURE_OT") || - STRPREFIX(opname, "SKETCH_OT")) - { - km = WM_keymap_find_all(C, "Armature", 0, 0); - } - else if (STRPREFIX(opname, "POSE_OT") || - STRPREFIX(opname, "POSELIB_OT")) - { - km = WM_keymap_find_all(C, "Pose", 0, 0); - } - else if (STRPREFIX(opname, "SCULPT_OT")) { - switch (CTX_data_mode_enum(C)) { - case CTX_MODE_SCULPT: - km = WM_keymap_find_all(C, "Sculpt", 0, 0); - break; - case CTX_MODE_EDIT_MESH: - km = WM_keymap_find_all(C, "UV Sculpt", 0, 0); - break; - default: - break; - } - } - else if (STRPREFIX(opname, "MBALL_OT")) { - km = WM_keymap_find_all(C, "Metaball", 0, 0); + /* some mball operators are active in object mode too, like add-prim */ + if (km && !WM_keymap_poll((bContext *)C, km)) { + km = WM_keymap_find_all(C, "Object Mode", 0, 0); + } + } + else if (STRPREFIX(opname, "LATTICE_OT")) { + km = WM_keymap_find_all(C, "Lattice", 0, 0); + } + else if (STRPREFIX(opname, "PARTICLE_OT")) { + km = WM_keymap_find_all(C, "Particle", 0, 0); + } + else if (STRPREFIX(opname, "FONT_OT")) { + km = WM_keymap_find_all(C, "Font", 0, 0); + } + /* Paint Face Mask */ + else if (STRPREFIX(opname, "PAINT_OT_face_select")) { + km = WM_keymap_find_all(C, "Face Mask", 0, 0); + } + else if (STRPREFIX(opname, "PAINT_OT")) { + /* check for relevant mode */ + switch (CTX_data_mode_enum(C)) { + case CTX_MODE_PAINT_WEIGHT: + km = WM_keymap_find_all(C, "Weight Paint", 0, 0); + break; + case CTX_MODE_PAINT_VERTEX: + km = WM_keymap_find_all(C, "Vertex Paint", 0, 0); + break; + case CTX_MODE_PAINT_TEXTURE: + km = WM_keymap_find_all(C, "Image Paint", 0, 0); + break; + case CTX_MODE_SCULPT: + km = WM_keymap_find_all(C, "Sculpt", 0, 0); + break; + default: + break; + } + } + /* Image Editor */ + else if (STRPREFIX(opname, "IMAGE_OT")) { + km = WM_keymap_find_all(C, "Image", sl->spacetype, 0); + } + /* Clip Editor */ + else if (STRPREFIX(opname, "CLIP_OT")) { + km = WM_keymap_find_all(C, "Clip", sl->spacetype, 0); + } + else if (STRPREFIX(opname, "MASK_OT")) { + km = WM_keymap_find_all(C, "Mask Editing", 0, 0); + } + /* UV Editor */ + else if (STRPREFIX(opname, "UV_OT")) { + /* Hack to allow using UV unwrapping ops from 3DView/editmode. + * Mesh keymap is probably not ideal, but best place I could find to put those. */ + if (sl->spacetype == SPACE_VIEW3D) { + km = WM_keymap_find_all(C, "Mesh", 0, 0); + if (km && !WM_keymap_poll((bContext *)C, km)) { + km = NULL; + } + } + if (!km) { + km = WM_keymap_find_all(C, "UV Editor", 0, 0); + } + } + /* Node Editor */ + else if (STRPREFIX(opname, "NODE_OT")) { + km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0); + } + /* Animation Editor Channels */ + else if (STRPREFIX(opname, "ANIM_OT_channels")) { + km = WM_keymap_find_all(C, "Animation Channels", 0, 0); + } + /* Animation Generic - after channels */ + else if (STRPREFIX(opname, "ANIM_OT")) { + km = WM_keymap_find_all(C, "Animation", 0, 0); + } + /* Graph Editor */ + else if (STRPREFIX(opname, "GRAPH_OT")) { + km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0); + } + /* Dopesheet Editor */ + else if (STRPREFIX(opname, "ACTION_OT")) { + km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0); + } + /* NLA Editor */ + else if (STRPREFIX(opname, "NLA_OT")) { + km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0); + } + /* Script */ + else if (STRPREFIX(opname, "SCRIPT_OT")) { + km = WM_keymap_find_all(C, "Script", sl->spacetype, 0); + } + /* Text */ + else if (STRPREFIX(opname, "TEXT_OT")) { + km = WM_keymap_find_all(C, "Text", sl->spacetype, 0); + } + /* Sequencer */ + else if (STRPREFIX(opname, "SEQUENCER_OT")) { + km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0); + } + /* Console */ + else if (STRPREFIX(opname, "CONSOLE_OT")) { + km = WM_keymap_find_all(C, "Console", sl->spacetype, 0); + } + /* Console */ + else if (STRPREFIX(opname, "INFO_OT")) { + km = WM_keymap_find_all(C, "Info", sl->spacetype, 0); + } + /* File browser */ + else if (STRPREFIX(opname, "FILE_OT")) { + km = WM_keymap_find_all(C, "File Browser", sl->spacetype, 0); + } + /* Logic Editor */ + else if (STRPREFIX(opname, "LOGIC_OT")) { + km = WM_keymap_find_all(C, "Logic Editor", sl->spacetype, 0); + } + /* Outliner */ + else if (STRPREFIX(opname, "OUTLINER_OT")) { + km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0); + } + /* Transform */ + else if (STRPREFIX(opname, "TRANSFORM_OT")) { + /* check for relevant editor */ + switch (sl->spacetype) { + case SPACE_VIEW3D: + km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0); + break; + case SPACE_GRAPH: + km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0); + break; + case SPACE_ACTION: + km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0); + break; + case SPACE_NLA: + km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0); + break; + case SPACE_IMAGE: + km = WM_keymap_find_all(C, "UV Editor", 0, 0); + break; + case SPACE_NODE: + km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0); + break; + case SPACE_SEQ: + km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0); + break; + } + } - /* some mball operators are active in object mode too, like add-prim */ - if (km && !WM_keymap_poll((bContext *)C, km)) { - km = WM_keymap_find_all(C, "Object Mode", 0, 0); - } - } - else if (STRPREFIX(opname, "LATTICE_OT")) { - km = WM_keymap_find_all(C, "Lattice", 0, 0); - } - else if (STRPREFIX(opname, "PARTICLE_OT")) { - km = WM_keymap_find_all(C, "Particle", 0, 0); - } - else if (STRPREFIX(opname, "FONT_OT")) { - km = WM_keymap_find_all(C, "Font", 0, 0); - } - /* Paint Face Mask */ - else if (STRPREFIX(opname, "PAINT_OT_face_select")) { - km = WM_keymap_find_all(C, "Face Mask", 0, 0); - } - else if (STRPREFIX(opname, "PAINT_OT")) { - /* check for relevant mode */ - switch (CTX_data_mode_enum(C)) { - case CTX_MODE_PAINT_WEIGHT: - km = WM_keymap_find_all(C, "Weight Paint", 0, 0); - break; - case CTX_MODE_PAINT_VERTEX: - km = WM_keymap_find_all(C, "Vertex Paint", 0, 0); - break; - case CTX_MODE_PAINT_TEXTURE: - km = WM_keymap_find_all(C, "Image Paint", 0, 0); - break; - case CTX_MODE_SCULPT: - km = WM_keymap_find_all(C, "Sculpt", 0, 0); - break; - default: - break; - } - } - /* Image Editor */ - else if (STRPREFIX(opname, "IMAGE_OT")) { - km = WM_keymap_find_all(C, "Image", sl->spacetype, 0); - } - /* Clip Editor */ - else if (STRPREFIX(opname, "CLIP_OT")) { - km = WM_keymap_find_all(C, "Clip", sl->spacetype, 0); - } - else if (STRPREFIX(opname, "MASK_OT")) { - km = WM_keymap_find_all(C, "Mask Editing", 0, 0); - } - /* UV Editor */ - else if (STRPREFIX(opname, "UV_OT")) { - /* Hack to allow using UV unwrapping ops from 3DView/editmode. - * Mesh keymap is probably not ideal, but best place I could find to put those. */ - if (sl->spacetype == SPACE_VIEW3D) { - km = WM_keymap_find_all(C, "Mesh", 0, 0); - if (km && !WM_keymap_poll((bContext *)C, km)) { - km = NULL; - } - } - if (!km) { - km = WM_keymap_find_all(C, "UV Editor", 0, 0); - } - } - /* Node Editor */ - else if (STRPREFIX(opname, "NODE_OT")) { - km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0); - } - /* Animation Editor Channels */ - else if (STRPREFIX(opname, "ANIM_OT_channels")) { - km = WM_keymap_find_all(C, "Animation Channels", 0, 0); - } - /* Animation Generic - after channels */ - else if (STRPREFIX(opname, "ANIM_OT")) { - km = WM_keymap_find_all(C, "Animation", 0, 0); - } - /* Graph Editor */ - else if (STRPREFIX(opname, "GRAPH_OT")) { - km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0); - } - /* Dopesheet Editor */ - else if (STRPREFIX(opname, "ACTION_OT")) { - km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0); - } - /* NLA Editor */ - else if (STRPREFIX(opname, "NLA_OT")) { - km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0); - } - /* Script */ - else if (STRPREFIX(opname, "SCRIPT_OT")) { - km = WM_keymap_find_all(C, "Script", sl->spacetype, 0); - } - /* Text */ - else if (STRPREFIX(opname, "TEXT_OT")) { - km = WM_keymap_find_all(C, "Text", sl->spacetype, 0); - } - /* Sequencer */ - else if (STRPREFIX(opname, "SEQUENCER_OT")) { - km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0); - } - /* Console */ - else if (STRPREFIX(opname, "CONSOLE_OT")) { - km = WM_keymap_find_all(C, "Console", sl->spacetype, 0); - } - /* Console */ - else if (STRPREFIX(opname, "INFO_OT")) { - km = WM_keymap_find_all(C, "Info", sl->spacetype, 0); - } - /* File browser */ - else if (STRPREFIX(opname, "FILE_OT")) { - km = WM_keymap_find_all(C, "File Browser", sl->spacetype, 0); - } - /* Logic Editor */ - else if (STRPREFIX(opname, "LOGIC_OT")) { - km = WM_keymap_find_all(C, "Logic Editor", sl->spacetype, 0); - } - /* Outliner */ - else if (STRPREFIX(opname, "OUTLINER_OT")) { - km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0); - } - /* Transform */ - else if (STRPREFIX(opname, "TRANSFORM_OT")) { - /* check for relevant editor */ - switch (sl->spacetype) { - case SPACE_VIEW3D: - km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0); - break; - case SPACE_GRAPH: - km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0); - break; - case SPACE_ACTION: - km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0); - break; - case SPACE_NLA: - km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0); - break; - case SPACE_IMAGE: - km = WM_keymap_find_all(C, "UV Editor", 0, 0); - break; - case SPACE_NODE: - km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0); - break; - case SPACE_SEQ: - km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0); - break; - } - } - - return km; + return km; } void WM_keymap_fix_linking(void) diff --git a/source/blender/windowmanager/intern/wm_menu_type.c b/source/blender/windowmanager/intern/wm_menu_type.c index f466ac44939..f657eb951bf 100644 --- a/source/blender/windowmanager/intern/wm_menu_type.c +++ b/source/blender/windowmanager/intern/wm_menu_type.c @@ -41,73 +41,73 @@ static GHash *menutypes_hash = NULL; MenuType *WM_menutype_find(const char *idname, bool quiet) { - MenuType *mt; + MenuType *mt; - if (idname[0]) { - mt = BLI_ghash_lookup(menutypes_hash, idname); - if (mt) { - return mt; - } - } + if (idname[0]) { + mt = BLI_ghash_lookup(menutypes_hash, idname); + if (mt) { + return mt; + } + } - if (!quiet) { - printf("search for unknown menutype %s\n", idname); - } + if (!quiet) { + printf("search for unknown menutype %s\n", idname); + } - return NULL; + return NULL; } bool WM_menutype_add(MenuType *mt) { - BLI_assert((mt->description == NULL) || (mt->description[0])); - BLI_ghash_insert(menutypes_hash, mt->idname, mt); - return true; + BLI_assert((mt->description == NULL) || (mt->description[0])); + BLI_ghash_insert(menutypes_hash, mt->idname, mt); + return true; } void WM_menutype_freelink(MenuType *mt) { - bool ok; + bool ok; - ok = BLI_ghash_remove(menutypes_hash, mt->idname, NULL, MEM_freeN); + ok = BLI_ghash_remove(menutypes_hash, mt->idname, NULL, MEM_freeN); - BLI_assert(ok); - (void)ok; + BLI_assert(ok); + (void)ok; } /* called on initialize WM_init() */ void WM_menutype_init(void) { - /* reserve size is set based on blender default setup */ - menutypes_hash = BLI_ghash_str_new_ex("menutypes_hash gh", 512); + /* reserve size is set based on blender default setup */ + menutypes_hash = BLI_ghash_str_new_ex("menutypes_hash gh", 512); } void WM_menutype_free(void) { - GHashIterator gh_iter; + GHashIterator gh_iter; - GHASH_ITER (gh_iter, menutypes_hash) { - MenuType *mt = BLI_ghashIterator_getValue(&gh_iter); - if (mt->ext.free) { - mt->ext.free(mt->ext.data); - } - } + GHASH_ITER (gh_iter, menutypes_hash) { + MenuType *mt = BLI_ghashIterator_getValue(&gh_iter); + if (mt->ext.free) { + mt->ext.free(mt->ext.data); + } + } - BLI_ghash_free(menutypes_hash, NULL, MEM_freeN); - menutypes_hash = NULL; + BLI_ghash_free(menutypes_hash, NULL, MEM_freeN); + menutypes_hash = NULL; } bool WM_menutype_poll(bContext *C, MenuType *mt) { - /* If we're tagged, only use compatible. */ - if (mt->owner_id[0] != '\0') { - const WorkSpace *workspace = CTX_wm_workspace(C); - if (BKE_workspace_owner_id_check(workspace, mt->owner_id) == false) { - return false; - } - } - - if (mt->poll != NULL) { - return mt->poll(C, mt); - } - return true; + /* If we're tagged, only use compatible. */ + if (mt->owner_id[0] != '\0') { + const WorkSpace *workspace = CTX_wm_workspace(C); + if (BKE_workspace_owner_id_check(workspace, mt->owner_id) == false) { + return false; + } + } + + if (mt->poll != NULL) { + return mt->poll(C, mt); + } + return true; } diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 55b45adbe2d..39594a66e4e 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -40,142 +40,193 @@ #include "WM_api.h" #include "WM_types.h" - void WM_operator_properties_confirm_or_exec(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - prop = RNA_def_boolean(ot->srna, "confirm", true, "Confirm", "Prompt for confirmation"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "confirm", true, "Confirm", "Prompt for confirmation"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /* default properties for fileselect */ -void WM_operator_properties_filesel( - wmOperatorType *ot, int filter, short type, short action, - short flag, short display, short sort) +void WM_operator_properties_filesel(wmOperatorType *ot, + int filter, + short type, + short action, + short flag, + short display, + short sort) { - PropertyRNA *prop; - - static const EnumPropertyItem file_display_items[] = { - {FILE_DEFAULTDISPLAY, "DEFAULT", 0, "Default", "Automatically determine display type for files"}, - {FILE_SHORTDISPLAY, "LIST_SHORT", ICON_SHORTDISPLAY, "Short List", "Display files as short list"}, - {FILE_LONGDISPLAY, "LIST_LONG", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"}, - {FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"}, - {0, NULL, 0, NULL, NULL}, - }; - - if (flag & WM_FILESEL_FILEPATH) { - RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Path to file"); - } - - if (flag & WM_FILESEL_DIRECTORY) { - RNA_def_string_dir_path(ot->srna, "directory", NULL, FILE_MAX, "Directory", "Directory of the file"); - } - - if (flag & WM_FILESEL_FILENAME) { - RNA_def_string_file_name(ot->srna, "filename", NULL, FILE_MAX, "File Name", "Name of the file"); - } - - if (flag & WM_FILESEL_FILES) { - RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); - } - - if (action == FILE_SAVE) { - /* note, this is only used to check if we should highlight the filename area red when the - * filepath is an existing file. */ - prop = RNA_def_boolean(ot->srna, "check_existing", true, "Check Existing", - "Check and warn on overwriting existing files"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - } - - prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & FILE_TYPE_BLENDER) != 0, "Filter .blend files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & FILE_TYPE_BLENDER_BACKUP) != 0, "Filter .blend files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_image", (filter & FILE_TYPE_IMAGE) != 0, "Filter image files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & FILE_TYPE_MOVIE) != 0, "Filter movie files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_python", (filter & FILE_TYPE_PYSCRIPT) != 0, "Filter python files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_font", (filter & FILE_TYPE_FTFONT) != 0, "Filter font files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_sound", (filter & FILE_TYPE_SOUND) != 0, "Filter sound files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_text", (filter & FILE_TYPE_TEXT) != 0, "Filter text files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_btx", (filter & FILE_TYPE_BTX) != 0, "Filter btx files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & FILE_TYPE_COLLADA) != 0, "Filter COLLADA files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_alembic", (filter & FILE_TYPE_ALEMBIC) != 0, "Filter Alembic files", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FILE_TYPE_FOLDER) != 0, "Filter folders", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "filter_blenlib", (filter & FILE_TYPE_BLENDERLIB) != 0, "Filter Blender IDs", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - - prop = RNA_def_int(ot->srna, "filemode", type, FILE_LOADLIB, FILE_SPECIAL, - "File Browser Mode", "The setting for the file browser mode to load a .blend file, a library or a special file", - FILE_LOADLIB, FILE_SPECIAL); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - - if (flag & WM_FILESEL_RELPATH) { - RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file"); - } - - if ((filter & FILE_TYPE_IMAGE) || (filter & FILE_TYPE_MOVIE)) { - prop = RNA_def_boolean(ot->srna, "show_multiview", 0, "Enable Multi-View", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_multiview", 0, "Use Multi-View", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - } - - prop = RNA_def_enum(ot->srna, "display_type", file_display_items, display, "Display Type", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - - prop = RNA_def_enum(ot->srna, "sort_method", rna_enum_file_sort_items, sort, "File sorting mode", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - + PropertyRNA *prop; + + static const EnumPropertyItem file_display_items[] = { + {FILE_DEFAULTDISPLAY, + "DEFAULT", + 0, + "Default", + "Automatically determine display type for files"}, + {FILE_SHORTDISPLAY, + "LIST_SHORT", + ICON_SHORTDISPLAY, + "Short List", + "Display files as short list"}, + {FILE_LONGDISPLAY, + "LIST_LONG", + ICON_LONGDISPLAY, + "Long List", + "Display files as a detailed list"}, + {FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"}, + {0, NULL, 0, NULL, NULL}, + }; + + if (flag & WM_FILESEL_FILEPATH) { + RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Path to file"); + } + + if (flag & WM_FILESEL_DIRECTORY) { + RNA_def_string_dir_path( + ot->srna, "directory", NULL, FILE_MAX, "Directory", "Directory of the file"); + } + + if (flag & WM_FILESEL_FILENAME) { + RNA_def_string_file_name( + ot->srna, "filename", NULL, FILE_MAX, "File Name", "Name of the file"); + } + + if (flag & WM_FILESEL_FILES) { + RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); + } + + if (action == FILE_SAVE) { + /* note, this is only used to check if we should highlight the filename area red when the + * filepath is an existing file. */ + prop = RNA_def_boolean(ot->srna, + "check_existing", + true, + "Check Existing", + "Check and warn on overwriting existing files"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + } + + prop = RNA_def_boolean( + ot->srna, "filter_blender", (filter & FILE_TYPE_BLENDER) != 0, "Filter .blend files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, + "filter_backup", + (filter & FILE_TYPE_BLENDER_BACKUP) != 0, + "Filter .blend files", + ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_image", (filter & FILE_TYPE_IMAGE) != 0, "Filter image files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_movie", (filter & FILE_TYPE_MOVIE) != 0, "Filter movie files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_python", (filter & FILE_TYPE_PYSCRIPT) != 0, "Filter python files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_font", (filter & FILE_TYPE_FTFONT) != 0, "Filter font files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_sound", (filter & FILE_TYPE_SOUND) != 0, "Filter sound files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_text", (filter & FILE_TYPE_TEXT) != 0, "Filter text files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_btx", (filter & FILE_TYPE_BTX) != 0, "Filter btx files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_collada", (filter & FILE_TYPE_COLLADA) != 0, "Filter COLLADA files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_alembic", (filter & FILE_TYPE_ALEMBIC) != 0, "Filter Alembic files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_folder", (filter & FILE_TYPE_FOLDER) != 0, "Filter folders", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "filter_blenlib", (filter & FILE_TYPE_BLENDERLIB) != 0, "Filter Blender IDs", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_int( + ot->srna, + "filemode", + type, + FILE_LOADLIB, + FILE_SPECIAL, + "File Browser Mode", + "The setting for the file browser mode to load a .blend file, a library or a special file", + FILE_LOADLIB, + FILE_SPECIAL); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + if (flag & WM_FILESEL_RELPATH) { + RNA_def_boolean(ot->srna, + "relative_path", + true, + "Relative Path", + "Select the file relative to the blend file"); + } + + if ((filter & FILE_TYPE_IMAGE) || (filter & FILE_TYPE_MOVIE)) { + prop = RNA_def_boolean(ot->srna, "show_multiview", 0, "Enable Multi-View", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_multiview", 0, "Use Multi-View", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + } + + prop = RNA_def_enum(ot->srna, "display_type", file_display_items, display, "Display Type", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_enum( + ot->srna, "sort_method", rna_enum_file_sort_items, sort, "File sorting mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -static void wm_operator_properties_select_action_ex(wmOperatorType *ot, int default_action, +static void wm_operator_properties_select_action_ex(wmOperatorType *ot, + int default_action, const EnumPropertyItem *select_actions, - bool hide_gui) + bool hide_gui) { - PropertyRNA *prop; - prop = RNA_def_enum(ot->srna, "action", select_actions, default_action, "Action", "Selection action to execute"); + PropertyRNA *prop; + prop = RNA_def_enum( + ot->srna, "action", select_actions, default_action, "Action", "Selection action to execute"); - if (hide_gui) { - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - } + if (hide_gui) { + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + } } void WM_operator_properties_select_action(wmOperatorType *ot, int default_action, bool hide_gui) { - static const EnumPropertyItem select_actions[] = { - {SEL_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle selection for all elements"}, - {SEL_SELECT, "SELECT", 0, "Select", "Select all elements"}, - {SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"}, - {SEL_INVERT, "INVERT", 0, "Invert", "Invert selection of all elements"}, - {0, NULL, 0, NULL, NULL}, - }; - - wm_operator_properties_select_action_ex(ot, default_action, select_actions, hide_gui); + static const EnumPropertyItem select_actions[] = { + {SEL_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle selection for all elements"}, + {SEL_SELECT, "SELECT", 0, "Select", "Select all elements"}, + {SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"}, + {SEL_INVERT, "INVERT", 0, "Invert", "Invert selection of all elements"}, + {0, NULL, 0, NULL, NULL}, + }; + + wm_operator_properties_select_action_ex(ot, default_action, select_actions, hide_gui); } /** * only SELECT/DESELECT */ -void WM_operator_properties_select_action_simple(wmOperatorType *ot, int default_action, bool hide_gui) +void WM_operator_properties_select_action_simple(wmOperatorType *ot, + int default_action, + bool hide_gui) { - static const EnumPropertyItem select_actions[] = { - {SEL_SELECT, "SELECT", 0, "Select", "Select all elements"}, - {SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem select_actions[] = { + {SEL_SELECT, "SELECT", 0, "Select", "Select all elements"}, + {SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"}, + {0, NULL, 0, NULL, NULL}, + }; - wm_operator_properties_select_action_ex(ot, default_action, select_actions, hide_gui); + wm_operator_properties_select_action_ex(ot, default_action, select_actions, hide_gui); } /** @@ -184,65 +235,77 @@ void WM_operator_properties_select_action_simple(wmOperatorType *ot, int default */ void WM_operator_properties_select_random(wmOperatorType *ot) { - RNA_def_float_percentage( - ot->srna, "percent", 50.f, 0.0f, 100.0f, - "Percent", "Percentage of objects to select randomly", 0.f, 100.0f); - RNA_def_int( - ot->srna, "seed", 0, 0, INT_MAX, - "Random Seed", "Seed for the random number generator", 0, 255); - - WM_operator_properties_select_action_simple(ot, SEL_SELECT, false); + RNA_def_float_percentage(ot->srna, + "percent", + 50.f, + 0.0f, + 100.0f, + "Percent", + "Percentage of objects to select randomly", + 0.f, + 100.0f); + RNA_def_int(ot->srna, + "seed", + 0, + 0, + INT_MAX, + "Random Seed", + "Seed for the random number generator", + 0, + 255); + + WM_operator_properties_select_action_simple(ot, SEL_SELECT, false); } int WM_operator_properties_select_random_seed_increment_get(wmOperator *op) { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "seed"); - int value = RNA_property_int_get(op->ptr, prop); - - if (op->flag & OP_IS_INVOKE) { - if (!RNA_property_is_set(op->ptr, prop)) { - value += 1; - RNA_property_int_set(op->ptr, prop, value); - } - } - return value; + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "seed"); + int value = RNA_property_int_get(op->ptr, prop); + + if (op->flag & OP_IS_INVOKE) { + if (!RNA_property_is_set(op->ptr, prop)) { + value += 1; + RNA_property_int_set(op->ptr, prop, value); + } + } + return value; } void WM_operator_properties_select_all(wmOperatorType *ot) { - WM_operator_properties_select_action(ot, SEL_TOGGLE, true); + WM_operator_properties_select_action(ot, SEL_TOGGLE, true); } void WM_operator_properties_border(wmOperatorType *ot) { - PropertyRNA *prop; - - prop = RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - - prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + PropertyRNA *prop; + + prop = RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect) { - rect->xmin = RNA_int_get(op->ptr, "xmin"); - rect->ymin = RNA_int_get(op->ptr, "ymin"); - rect->xmax = RNA_int_get(op->ptr, "xmax"); - rect->ymax = RNA_int_get(op->ptr, "ymax"); + rect->xmin = RNA_int_get(op->ptr, "xmin"); + rect->ymin = RNA_int_get(op->ptr, "ymin"); + rect->xmax = RNA_int_get(op->ptr, "xmax"); + rect->ymax = RNA_int_get(op->ptr, "ymax"); } void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect) { - rcti rect_i; - WM_operator_properties_border_to_rcti(op, &rect_i); - BLI_rctf_rcti_copy(rect, &rect_i); + rcti rect_i; + WM_operator_properties_border_to_rcti(op, &rect_i); + BLI_rctf_rcti_copy(rect, &rect_i); } /** @@ -250,63 +313,68 @@ void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect) */ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bool extend) { - PropertyRNA *prop; - - WM_operator_properties_border(ot); - - if (deselect) { - prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - } - if (extend) { - prop = RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - } + PropertyRNA *prop; + + WM_operator_properties_border(ot); + + if (deselect) { + prop = RNA_def_boolean( + ot->srna, "deselect", false, "Deselect", "Deselect rather than select items"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + } + if (extend) { + prop = RNA_def_boolean(ot->srna, + "extend", + true, + "Extend", + "Extend selection instead of deselecting everything first"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + } } void WM_operator_properties_gesture_box_select(wmOperatorType *ot) { - WM_operator_properties_gesture_box_ex(ot, true, true); + WM_operator_properties_gesture_box_ex(ot, true, true); } void WM_operator_properties_gesture_box(wmOperatorType *ot) { - WM_operator_properties_gesture_box_ex(ot, false, false); + WM_operator_properties_gesture_box_ex(ot, false, false); } void WM_operator_properties_select_operation(wmOperatorType *ot) { - static const EnumPropertyItem select_mode_items[] = { - {SEL_OP_SET, "SET", 0, "New", ""}, - {SEL_OP_ADD, "ADD", 0, "Add", ""}, - {SEL_OP_SUB, "SUB", 0, "Subtract", ""}, - {SEL_OP_XOR, "XOR", 0, "Difference", ""}, - {SEL_OP_AND, "AND", 0, "Intersect", ""}, - {0, NULL, 0, NULL, NULL}, - }; - PropertyRNA *prop = RNA_def_enum(ot->srna, "mode", select_mode_items, SEL_OP_SET, "Mode", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + static const EnumPropertyItem select_mode_items[] = { + {SEL_OP_SET, "SET", 0, "New", ""}, + {SEL_OP_ADD, "ADD", 0, "Add", ""}, + {SEL_OP_SUB, "SUB", 0, "Subtract", ""}, + {SEL_OP_XOR, "XOR", 0, "Difference", ""}, + {SEL_OP_AND, "AND", 0, "Intersect", ""}, + {0, NULL, 0, NULL, NULL}, + }; + PropertyRNA *prop = RNA_def_enum(ot->srna, "mode", select_mode_items, SEL_OP_SET, "Mode", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* Some tools don't support XOR/AND. */ void WM_operator_properties_select_operation_simple(wmOperatorType *ot) { - static const EnumPropertyItem select_mode_items[] = { - {SEL_OP_SET, "SET", 0, "New", ""}, - {SEL_OP_ADD, "ADD", 0, "Add", ""}, - {SEL_OP_SUB, "SUB", 0, "Subtract", ""}, - {0, NULL, 0, NULL, NULL}, - }; - PropertyRNA *prop = RNA_def_enum(ot->srna, "mode", select_mode_items, SEL_OP_SET, "Mode", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + static const EnumPropertyItem select_mode_items[] = { + {SEL_OP_SET, "SET", 0, "New", ""}, + {SEL_OP_ADD, "ADD", 0, "Add", ""}, + {SEL_OP_SUB, "SUB", 0, "Subtract", ""}, + {0, NULL, 0, NULL, NULL}, + }; + PropertyRNA *prop = RNA_def_enum(ot->srna, "mode", select_mode_items, SEL_OP_SET, "Mode", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot) { - WM_operator_properties_border(ot); + WM_operator_properties_border(ot); - PropertyRNA *prop; - prop = RNA_def_boolean(ot->srna, "zoom_out", false, "Zoom Out", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + PropertyRNA *prop; + prop = RNA_def_boolean(ot->srna, "zoom_out", false, "Zoom Out", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** @@ -314,9 +382,9 @@ void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot) */ void WM_operator_properties_gesture_lasso(wmOperatorType *ot) { - PropertyRNA *prop; - prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + PropertyRNA *prop; + prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** @@ -324,22 +392,29 @@ void WM_operator_properties_gesture_lasso(wmOperatorType *ot) */ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) { - PropertyRNA *prop; - - prop = RNA_def_int(ot->srna, "xstart", 0, INT_MIN, INT_MAX, "X Start", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_int(ot->srna, "xend", 0, INT_MIN, INT_MAX, "X End", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_int(ot->srna, "ystart", 0, INT_MIN, INT_MAX, "Y Start", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - - if (cursor) { - prop = RNA_def_int(ot->srna, "cursor", cursor, 0, INT_MAX, - "Cursor", "Mouse cursor style to use during the modal operator", 0, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN); - } + PropertyRNA *prop; + + prop = RNA_def_int(ot->srna, "xstart", 0, INT_MIN, INT_MAX, "X Start", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "xend", 0, INT_MIN, INT_MAX, "X End", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "ystart", 0, INT_MIN, INT_MAX, "Y Start", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + if (cursor) { + prop = RNA_def_int(ot->srna, + "cursor", + cursor, + 0, + INT_MAX, + "Cursor", + "Mouse cursor style to use during the modal operator", + 0, + INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); + } } /** @@ -347,30 +422,33 @@ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) */ void WM_operator_properties_gesture_circle(wmOperatorType *ot) { - PropertyRNA *prop; - const int radius_default = 25; + PropertyRNA *prop; + const int radius_default = 25; - prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - RNA_def_int(ot->srna, "radius", radius_default, 1, INT_MAX, "Radius", "", 1, INT_MAX); + prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_int(ot->srna, "radius", radius_default, 1, INT_MAX, "Radius", "", 1, INT_MAX); - prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } void WM_operator_properties_mouse_select(wmOperatorType *ot) { - PropertyRNA *prop; - - prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", - "Extend selection instead of deselecting everything first"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Remove from selection"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle Selection", "Toggle the selection"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + prop = RNA_def_boolean(ot->srna, + "extend", + false, + "Extend", + "Extend selection instead of deselecting everything first"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Remove from selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle Selection", "Toggle the selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** @@ -378,28 +456,46 @@ void WM_operator_properties_mouse_select(wmOperatorType *ot) */ void WM_operator_properties_checker_interval(wmOperatorType *ot, bool nth_can_disable) { - const int nth_default = nth_can_disable ? 1 : 2; - const int nth_min = min_ii(nth_default, 2); - RNA_def_int(ot->srna, "nth", nth_default, nth_min, INT_MAX, "Nth Element", "Skip every Nth element", nth_min, 100); - RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "Number of elements to skip at once", 1, 100); - RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "Offset from the starting point", -100, 100); + const int nth_default = nth_can_disable ? 1 : 2; + const int nth_min = min_ii(nth_default, 2); + RNA_def_int(ot->srna, + "nth", + nth_default, + nth_min, + INT_MAX, + "Nth Element", + "Skip every Nth element", + nth_min, + 100); + RNA_def_int( + ot->srna, "skip", 1, 1, INT_MAX, "Skip", "Number of elements to skip at once", 1, 100); + RNA_def_int(ot->srna, + "offset", + 0, + INT_MIN, + INT_MAX, + "Offset", + "Offset from the starting point", + -100, + 100); } -void WM_operator_properties_checker_interval_from_op( - struct wmOperator *op, struct CheckerIntervalParams *op_params) +void WM_operator_properties_checker_interval_from_op(struct wmOperator *op, + struct CheckerIntervalParams *op_params) { - const int nth = RNA_int_get(op->ptr, "nth") - 1; - const int skip = RNA_int_get(op->ptr, "skip"); - int offset = RNA_int_get(op->ptr, "offset"); - - op_params->nth = nth; - op_params->skip = skip; - op_params->offset = mod_i(offset, nth + skip); /* so input of offset zero ends up being (nth - 1) */ + const int nth = RNA_int_get(op->ptr, "nth") - 1; + const int skip = RNA_int_get(op->ptr, "skip"); + int offset = RNA_int_get(op->ptr, "offset"); + + op_params->nth = nth; + op_params->skip = skip; + op_params->offset = mod_i(offset, + nth + skip); /* so input of offset zero ends up being (nth - 1) */ } -bool WM_operator_properties_checker_interval_test( - const struct CheckerIntervalParams *op_params, int depth) +bool WM_operator_properties_checker_interval_test(const struct CheckerIntervalParams *op_params, + int depth) { - return ((op_params->nth == 0) || - ((op_params->offset + depth) % (op_params->skip + op_params->nth) >= op_params->skip)); + return ((op_params->nth == 0) || + ((op_params->offset + depth) % (op_params->skip + op_params->nth) >= op_params->skip)); } diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c index 606fb822e67..63caf6126cc 100644 --- a/source/blender/windowmanager/intern/wm_operator_type.c +++ b/source/blender/windowmanager/intern/wm_operator_type.c @@ -63,35 +63,36 @@ static int ot_prop_basic_count = -1; wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) { - if (idname[0]) { - wmOperatorType *ot; - - /* needed to support python style names without the _OT_ syntax */ - char idname_bl[OP_MAX_TYPENAME]; - WM_operator_bl_idname(idname_bl, idname); - - ot = BLI_ghash_lookup(global_ops_hash, idname_bl); - if (ot) { - return ot; - } - - if (!quiet) { - CLOG_INFO(WM_LOG_OPERATORS, 0, "search for unknown operator '%s', '%s'\n", idname_bl, idname); - } - } - else { - if (!quiet) { - CLOG_INFO(WM_LOG_OPERATORS, 0, "search for empty operator"); - } - } - - return NULL; + if (idname[0]) { + wmOperatorType *ot; + + /* needed to support python style names without the _OT_ syntax */ + char idname_bl[OP_MAX_TYPENAME]; + WM_operator_bl_idname(idname_bl, idname); + + ot = BLI_ghash_lookup(global_ops_hash, idname_bl); + if (ot) { + return ot; + } + + if (!quiet) { + CLOG_INFO( + WM_LOG_OPERATORS, 0, "search for unknown operator '%s', '%s'\n", idname_bl, idname); + } + } + else { + if (!quiet) { + CLOG_INFO(WM_LOG_OPERATORS, 0, "search for empty operator"); + } + } + + return NULL; } /* caller must free */ void WM_operatortype_iter(GHashIterator *ghi) { - BLI_ghashIterator_init(ghi, global_ops_hash); + BLI_ghashIterator_init(ghi, global_ops_hash); } /** \name Operator Type Append @@ -99,119 +100,119 @@ void WM_operatortype_iter(GHashIterator *ghi) static wmOperatorType *wm_operatortype_append__begin(void) { - wmOperatorType *ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); + wmOperatorType *ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); - BLI_assert(ot_prop_basic_count == -1); + BLI_assert(ot_prop_basic_count == -1); - ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); - RNA_def_struct_property_tags(ot->srna, rna_enum_operator_property_tags); - /* Set the default i18n context now, so that opfunc can redefine it if needed! */ - RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); - ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT; + ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); + RNA_def_struct_property_tags(ot->srna, rna_enum_operator_property_tags); + /* Set the default i18n context now, so that opfunc can redefine it if needed! */ + RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); + ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT; - return ot; + return ot; } static void wm_operatortype_append__end(wmOperatorType *ot) { - if (ot->name == NULL) { - CLOG_ERROR(WM_LOG_OPERATORS, "Operator '%s' has no name property", ot->idname); - } - BLI_assert((ot->description == NULL) || (ot->description[0])); + if (ot->name == NULL) { + CLOG_ERROR(WM_LOG_OPERATORS, "Operator '%s' has no name property", ot->idname); + } + BLI_assert((ot->description == NULL) || (ot->description[0])); - /* Allow calling _begin without _end in operatortype creation. */ - WM_operatortype_props_advanced_end(ot); + /* Allow calling _begin without _end in operatortype creation. */ + WM_operatortype_props_advanced_end(ot); - /* XXX All ops should have a description but for now allow them not to. */ - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP); - RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); + /* XXX All ops should have a description but for now allow them not to. */ + RNA_def_struct_ui_text( + ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP); + RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); - BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); + BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); } /* all ops in 1 list (for time being... needs evaluation later) */ void WM_operatortype_append(void (*opfunc)(wmOperatorType *)) { - wmOperatorType *ot = wm_operatortype_append__begin(); - opfunc(ot); - wm_operatortype_append__end(ot); + wmOperatorType *ot = wm_operatortype_append__begin(); + opfunc(ot); + wm_operatortype_append__end(ot); } void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata) { - wmOperatorType *ot = wm_operatortype_append__begin(); - opfunc(ot, userdata); - wm_operatortype_append__end(ot); + wmOperatorType *ot = wm_operatortype_append__begin(); + opfunc(ot, userdata); + wm_operatortype_append__end(ot); } /** \} */ - /* called on initialize WM_exit() */ void WM_operatortype_remove_ptr(wmOperatorType *ot) { - BLI_assert(ot == WM_operatortype_find(ot->idname, false)); + BLI_assert(ot == WM_operatortype_find(ot->idname, false)); - RNA_struct_free(&BLENDER_RNA, ot->srna); + RNA_struct_free(&BLENDER_RNA, ot->srna); - if (ot->last_properties) { - IDP_FreeProperty(ot->last_properties); - MEM_freeN(ot->last_properties); - } + if (ot->last_properties) { + IDP_FreeProperty(ot->last_properties); + MEM_freeN(ot->last_properties); + } - if (ot->macro.first) { - wm_operatortype_free_macro(ot); - } + if (ot->macro.first) { + wm_operatortype_free_macro(ot); + } - BLI_ghash_remove(global_ops_hash, ot->idname, NULL, NULL); + BLI_ghash_remove(global_ops_hash, ot->idname, NULL, NULL); - WM_keyconfig_update_operatortype(); + WM_keyconfig_update_operatortype(); - MEM_freeN(ot); + MEM_freeN(ot); } bool WM_operatortype_remove(const char *idname) { - wmOperatorType *ot = WM_operatortype_find(idname, 0); + wmOperatorType *ot = WM_operatortype_find(idname, 0); - if (ot == NULL) { - return false; - } + if (ot == NULL) { + return false; + } - WM_operatortype_remove_ptr(ot); + WM_operatortype_remove_ptr(ot); - return true; + return true; } /* called on initialize WM_init() */ void wm_operatortype_init(void) { - /* reserve size is set based on blender default setup */ - global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048); + /* reserve size is set based on blender default setup */ + global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048); } static void operatortype_ghash_free_cb(wmOperatorType *ot) { - if (ot->last_properties) { - IDP_FreeProperty(ot->last_properties); - MEM_freeN(ot->last_properties); - } + if (ot->last_properties) { + IDP_FreeProperty(ot->last_properties); + MEM_freeN(ot->last_properties); + } - if (ot->macro.first) { - wm_operatortype_free_macro(ot); - } + if (ot->macro.first) { + wm_operatortype_free_macro(ot); + } - if (ot->ext.srna) { - /* python operator, allocs own string */ - MEM_freeN((void *)ot->idname); - } + if (ot->ext.srna) { + /* python operator, allocs own string */ + MEM_freeN((void *)ot->idname); + } - MEM_freeN(ot); + MEM_freeN(ot); } void wm_operatortype_free(void) { - BLI_ghash_free(global_ops_hash, NULL, (GHashValFreeFP)operatortype_ghash_free_cb); - global_ops_hash = NULL; + BLI_ghash_free(global_ops_hash, NULL, (GHashValFreeFP)operatortype_ghash_free_cb); + global_ops_hash = NULL; } /** @@ -228,9 +229,10 @@ void wm_operatortype_free(void) */ void WM_operatortype_props_advanced_begin(wmOperatorType *ot) { - if (ot_prop_basic_count == -1) { /* Don't do anything if _begin was called before, but not _end */ - ot_prop_basic_count = RNA_struct_count_properties(ot->srna); - } + if (ot_prop_basic_count == + -1) { /* Don't do anything if _begin was called before, but not _end */ + ot_prop_basic_count = RNA_struct_count_properties(ot->srna); + } } /** @@ -241,26 +243,25 @@ void WM_operatortype_props_advanced_begin(wmOperatorType *ot) */ void WM_operatortype_props_advanced_end(wmOperatorType *ot) { - PointerRNA struct_ptr; - int counter = 0; - - if (ot_prop_basic_count == -1) { - /* WM_operatortype_props_advanced_begin was not called. Don't do anything. */ - return; - } - - RNA_pointer_create(NULL, ot->srna, NULL, &struct_ptr); - - RNA_STRUCT_BEGIN (&struct_ptr, prop) - { - counter++; - if (counter > ot_prop_basic_count) { - WM_operatortype_prop_tag(prop, OP_PROP_TAG_ADVANCED); - } - } - RNA_STRUCT_END; - - ot_prop_basic_count = -1; + PointerRNA struct_ptr; + int counter = 0; + + if (ot_prop_basic_count == -1) { + /* WM_operatortype_props_advanced_begin was not called. Don't do anything. */ + return; + } + + RNA_pointer_create(NULL, ot->srna, NULL, &struct_ptr); + + RNA_STRUCT_BEGIN (&struct_ptr, prop) { + counter++; + if (counter > ot_prop_basic_count) { + WM_operatortype_prop_tag(prop, OP_PROP_TAG_ADVANCED); + } + } + RNA_STRUCT_END; + + ot_prop_basic_count = -1; } /** @@ -268,20 +269,18 @@ void WM_operatortype_props_advanced_end(wmOperatorType *ot) */ void WM_operatortype_last_properties_clear_all(void) { - GHashIterator iter; - - for (WM_operatortype_iter(&iter); - (!BLI_ghashIterator_done(&iter)); - (BLI_ghashIterator_step(&iter))) - { - wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); - - if (ot->last_properties) { - IDP_FreeProperty(ot->last_properties); - MEM_freeN(ot->last_properties); - ot->last_properties = NULL; - } - } + GHashIterator iter; + + for (WM_operatortype_iter(&iter); (!BLI_ghashIterator_done(&iter)); + (BLI_ghashIterator_step(&iter))) { + wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); + + if (ot->last_properties) { + IDP_FreeProperty(ot->last_properties); + MEM_freeN(ot->last_properties); + ot->last_properties = NULL; + } + } } /** \} */ @@ -291,283 +290,290 @@ void WM_operatortype_last_properties_clear_all(void) * \{ */ typedef struct { - int retval; + int retval; } MacroData; static void wm_macro_start(wmOperator *op) { - if (op->customdata == NULL) { - op->customdata = MEM_callocN(sizeof(MacroData), "MacroData"); - } + if (op->customdata == NULL) { + op->customdata = MEM_callocN(sizeof(MacroData), "MacroData"); + } } static int wm_macro_end(wmOperator *op, int retval) { - if (retval & OPERATOR_CANCELLED) { - MacroData *md = op->customdata; - - if (md->retval & OPERATOR_FINISHED) { - retval |= OPERATOR_FINISHED; - retval &= ~OPERATOR_CANCELLED; - } - } - - /* if modal is ending, free custom data */ - if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { - if (op->customdata) { - MEM_freeN(op->customdata); - op->customdata = NULL; - } - } - - return retval; + if (retval & OPERATOR_CANCELLED) { + MacroData *md = op->customdata; + + if (md->retval & OPERATOR_FINISHED) { + retval |= OPERATOR_FINISHED; + retval &= ~OPERATOR_CANCELLED; + } + } + + /* if modal is ending, free custom data */ + if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { + if (op->customdata) { + MEM_freeN(op->customdata); + op->customdata = NULL; + } + } + + return retval; } /* macro exec only runs exec calls */ static int wm_macro_exec(bContext *C, wmOperator *op) { - wmOperator *opm; - int retval = OPERATOR_FINISHED; - - wm_macro_start(op); - - for (opm = op->macro.first; opm; opm = opm->next) { - - if (opm->type->exec) { - retval = opm->type->exec(C, opm); - OPERATOR_RETVAL_CHECK(retval); - - if (retval & OPERATOR_FINISHED) { - MacroData *md = op->customdata; - md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ - } - else { - break; /* operator didn't finish, end macro */ - } - } - else { - CLOG_WARN(WM_LOG_OPERATORS, "'%s' cant exec macro", opm->type->idname); - } - } - - return wm_macro_end(op, retval); + wmOperator *opm; + int retval = OPERATOR_FINISHED; + + wm_macro_start(op); + + for (opm = op->macro.first; opm; opm = opm->next) { + + if (opm->type->exec) { + retval = opm->type->exec(C, opm); + OPERATOR_RETVAL_CHECK(retval); + + if (retval & OPERATOR_FINISHED) { + MacroData *md = op->customdata; + md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ + } + else { + break; /* operator didn't finish, end macro */ + } + } + else { + CLOG_WARN(WM_LOG_OPERATORS, "'%s' cant exec macro", opm->type->idname); + } + } + + return wm_macro_end(op, retval); } -static int wm_macro_invoke_internal(bContext *C, wmOperator *op, const wmEvent *event, wmOperator *opm) +static int wm_macro_invoke_internal(bContext *C, + wmOperator *op, + const wmEvent *event, + wmOperator *opm) { - int retval = OPERATOR_FINISHED; - - /* start from operator received as argument */ - for (; opm; opm = opm->next) { - if (opm->type->invoke) { - retval = opm->type->invoke(C, opm, event); - } - else if (opm->type->exec) { - retval = opm->type->exec(C, opm); - } - - OPERATOR_RETVAL_CHECK(retval); - - BLI_movelisttolist(&op->reports->list, &opm->reports->list); - - if (retval & OPERATOR_FINISHED) { - MacroData *md = op->customdata; - md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ - } - else { - break; /* operator didn't finish, end macro */ - } - } - - return wm_macro_end(op, retval); + int retval = OPERATOR_FINISHED; + + /* start from operator received as argument */ + for (; opm; opm = opm->next) { + if (opm->type->invoke) { + retval = opm->type->invoke(C, opm, event); + } + else if (opm->type->exec) { + retval = opm->type->exec(C, opm); + } + + OPERATOR_RETVAL_CHECK(retval); + + BLI_movelisttolist(&op->reports->list, &opm->reports->list); + + if (retval & OPERATOR_FINISHED) { + MacroData *md = op->customdata; + md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ + } + else { + break; /* operator didn't finish, end macro */ + } + } + + return wm_macro_end(op, retval); } static int wm_macro_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - wm_macro_start(op); - return wm_macro_invoke_internal(C, op, event, op->macro.first); + wm_macro_start(op); + return wm_macro_invoke_internal(C, op, event, op->macro.first); } static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event) { - wmOperator *opm = op->opm; - int retval = OPERATOR_FINISHED; - - if (opm == NULL) { - CLOG_ERROR(WM_LOG_OPERATORS, "macro error, calling NULL modal()"); - } - else { - retval = opm->type->modal(C, opm, event); - OPERATOR_RETVAL_CHECK(retval); - - /* if we're halfway through using a tool and cancel it, clear the options [#37149] */ - if (retval & OPERATOR_CANCELLED) { - WM_operator_properties_clear(opm->ptr); - } - - /* if this one is done but it's not the last operator in the macro */ - if ((retval & OPERATOR_FINISHED) && opm->next) { - MacroData *md = op->customdata; - - md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ - - retval = wm_macro_invoke_internal(C, op, event, opm->next); - - /* if new operator is modal and also added its own handler */ - if (retval & OPERATOR_RUNNING_MODAL && op->opm != opm) { - wmWindow *win = CTX_wm_window(C); - wmEventHandler_Op *handler; - - handler = BLI_findptr(&win->modalhandlers, op, offsetof(wmEventHandler_Op, op)); - if (handler) { - BLI_remlink(&win->modalhandlers, handler); - wm_event_free_handler(&handler->head); - } - - /* if operator is blocking, grab cursor - * This may end up grabbing twice, but we don't care. - * */ - if (op->opm->type->flag & OPTYPE_BLOCKING) { - int bounds[4] = {-1, -1, -1, -1}; - const bool wrap = ( - (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR))); - - if (wrap) { - ARegion *ar = CTX_wm_region(C); - if (ar) { - bounds[0] = ar->winrct.xmin; - bounds[1] = ar->winrct.ymax; - bounds[2] = ar->winrct.xmax; - bounds[3] = ar->winrct.ymin; - } - } - - WM_cursor_grab_enable(win, wrap, false, bounds); - } - } - } - } - - return wm_macro_end(op, retval); + wmOperator *opm = op->opm; + int retval = OPERATOR_FINISHED; + + if (opm == NULL) { + CLOG_ERROR(WM_LOG_OPERATORS, "macro error, calling NULL modal()"); + } + else { + retval = opm->type->modal(C, opm, event); + OPERATOR_RETVAL_CHECK(retval); + + /* if we're halfway through using a tool and cancel it, clear the options [#37149] */ + if (retval & OPERATOR_CANCELLED) { + WM_operator_properties_clear(opm->ptr); + } + + /* if this one is done but it's not the last operator in the macro */ + if ((retval & OPERATOR_FINISHED) && opm->next) { + MacroData *md = op->customdata; + + md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ + + retval = wm_macro_invoke_internal(C, op, event, opm->next); + + /* if new operator is modal and also added its own handler */ + if (retval & OPERATOR_RUNNING_MODAL && op->opm != opm) { + wmWindow *win = CTX_wm_window(C); + wmEventHandler_Op *handler; + + handler = BLI_findptr(&win->modalhandlers, op, offsetof(wmEventHandler_Op, op)); + if (handler) { + BLI_remlink(&win->modalhandlers, handler); + wm_event_free_handler(&handler->head); + } + + /* if operator is blocking, grab cursor + * This may end up grabbing twice, but we don't care. + * */ + if (op->opm->type->flag & OPTYPE_BLOCKING) { + int bounds[4] = {-1, -1, -1, -1}; + const bool wrap = ((U.uiflag & USER_CONTINUOUS_MOUSE) && + ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || + (op->opm->type->flag & OPTYPE_GRAB_CURSOR))); + + if (wrap) { + ARegion *ar = CTX_wm_region(C); + if (ar) { + bounds[0] = ar->winrct.xmin; + bounds[1] = ar->winrct.ymax; + bounds[2] = ar->winrct.xmax; + bounds[3] = ar->winrct.ymin; + } + } + + WM_cursor_grab_enable(win, wrap, false, bounds); + } + } + } + } + + return wm_macro_end(op, retval); } static void wm_macro_cancel(bContext *C, wmOperator *op) { - /* call cancel on the current modal operator, if any */ - if (op->opm && op->opm->type->cancel) { - op->opm->type->cancel(C, op->opm); - } + /* call cancel on the current modal operator, if any */ + if (op->opm && op->opm->type->cancel) { + op->opm->type->cancel(C, op->opm); + } - wm_macro_end(op, OPERATOR_CANCELLED); + wm_macro_end(op, OPERATOR_CANCELLED); } /* Names have to be static for now */ -wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag) +wmOperatorType *WM_operatortype_append_macro(const char *idname, + const char *name, + const char *description, + int flag) { - wmOperatorType *ot; - const char *i18n_context; - - if (WM_operatortype_find(idname, true)) { - CLOG_ERROR(WM_LOG_OPERATORS, "operator %s exists, cannot create macro", idname); - return NULL; - } - - ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); - ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); - - ot->idname = idname; - ot->name = name; - ot->description = description; - ot->flag = OPTYPE_MACRO | flag; - - ot->exec = wm_macro_exec; - ot->invoke = wm_macro_invoke; - ot->modal = wm_macro_modal; - ot->cancel = wm_macro_cancel; - ot->poll = NULL; - - if (!ot->description) { - /* XXX All ops should have a description but for now allow them not to. */ - ot->description = UNDOCUMENTED_OPERATOR_TIP; - } - - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); - RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); - /* Use i18n context from ext.srna if possible (py operators). */ - i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : BLT_I18NCONTEXT_OPERATOR_DEFAULT; - RNA_def_struct_translation_context(ot->srna, i18n_context); - ot->translation_context = i18n_context; - - BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); - - return ot; + wmOperatorType *ot; + const char *i18n_context; + + if (WM_operatortype_find(idname, true)) { + CLOG_ERROR(WM_LOG_OPERATORS, "operator %s exists, cannot create macro", idname); + return NULL; + } + + ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); + ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); + + ot->idname = idname; + ot->name = name; + ot->description = description; + ot->flag = OPTYPE_MACRO | flag; + + ot->exec = wm_macro_exec; + ot->invoke = wm_macro_invoke; + ot->modal = wm_macro_modal; + ot->cancel = wm_macro_cancel; + ot->poll = NULL; + + if (!ot->description) { + /* XXX All ops should have a description but for now allow them not to. */ + ot->description = UNDOCUMENTED_OPERATOR_TIP; + } + + RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); + RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); + /* Use i18n context from ext.srna if possible (py operators). */ + i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : + BLT_I18NCONTEXT_OPERATOR_DEFAULT; + RNA_def_struct_translation_context(ot->srna, i18n_context); + ot->translation_context = i18n_context; + + BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); + + return ot; } void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata) { - wmOperatorType *ot; + wmOperatorType *ot; - ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); - ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); + ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); + ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); - ot->flag = OPTYPE_MACRO; - ot->exec = wm_macro_exec; - ot->invoke = wm_macro_invoke; - ot->modal = wm_macro_modal; - ot->cancel = wm_macro_cancel; - ot->poll = NULL; + ot->flag = OPTYPE_MACRO; + ot->exec = wm_macro_exec; + ot->invoke = wm_macro_invoke; + ot->modal = wm_macro_modal; + ot->cancel = wm_macro_cancel; + ot->poll = NULL; - if (!ot->description) { - ot->description = UNDOCUMENTED_OPERATOR_TIP; - } + if (!ot->description) { + ot->description = UNDOCUMENTED_OPERATOR_TIP; + } - /* Set the default i18n context now, so that opfunc can redefine it if needed! */ - RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); - ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT; - opfunc(ot, userdata); + /* Set the default i18n context now, so that opfunc can redefine it if needed! */ + RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); + ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT; + opfunc(ot, userdata); - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); - RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); + RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); + RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); - BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); + BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); } wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char *idname) { - wmOperatorTypeMacro *otmacro = MEM_callocN(sizeof(wmOperatorTypeMacro), "wmOperatorTypeMacro"); + wmOperatorTypeMacro *otmacro = MEM_callocN(sizeof(wmOperatorTypeMacro), "wmOperatorTypeMacro"); - BLI_strncpy(otmacro->idname, idname, OP_MAX_TYPENAME); + BLI_strncpy(otmacro->idname, idname, OP_MAX_TYPENAME); - /* do this on first use, since operatordefinitions might have been not done yet */ - WM_operator_properties_alloc(&(otmacro->ptr), &(otmacro->properties), idname); - WM_operator_properties_sanitize(otmacro->ptr, 1); + /* do this on first use, since operatordefinitions might have been not done yet */ + WM_operator_properties_alloc(&(otmacro->ptr), &(otmacro->properties), idname); + WM_operator_properties_sanitize(otmacro->ptr, 1); - BLI_addtail(&ot->macro, otmacro); + BLI_addtail(&ot->macro, otmacro); - { - /* operator should always be found but in the event its not. don't segfault */ - wmOperatorType *otsub = WM_operatortype_find(idname, 0); - if (otsub) { - RNA_def_pointer_runtime(ot->srna, otsub->idname, otsub->srna, - otsub->name, otsub->description); - } - } + { + /* operator should always be found but in the event its not. don't segfault */ + wmOperatorType *otsub = WM_operatortype_find(idname, 0); + if (otsub) { + RNA_def_pointer_runtime( + ot->srna, otsub->idname, otsub->srna, otsub->name, otsub->description); + } + } - return otmacro; + return otmacro; } static void wm_operatortype_free_macro(wmOperatorType *ot) { - wmOperatorTypeMacro *otmacro; - - for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { - if (otmacro->ptr) { - WM_operator_properties_free(otmacro->ptr); - MEM_freeN(otmacro->ptr); - } - } - BLI_freelistN(&ot->macro); + wmOperatorTypeMacro *otmacro; + + for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { + if (otmacro->ptr) { + WM_operator_properties_free(otmacro->ptr); + MEM_freeN(otmacro->ptr); + } + } + BLI_freelistN(&ot->macro); } /** \} */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1411b8af1fe..41cebec7e90 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -24,7 +24,6 @@ * as well as some generic operators and shared operator properties. */ - #include <float.h> #include <string.h> #include <ctype.h> @@ -120,86 +119,98 @@ /* SOME_OT_op -> some.op */ void WM_operator_py_idname(char *to, const char *from) { - const char *sep = strstr(from, "_OT_"); - if (sep) { - int ofs = (sep - from); + const char *sep = strstr(from, "_OT_"); + if (sep) { + 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 mismatch */ - memcpy(to, from, sizeof(char) * ofs); - BLI_str_tolower_ascii(to, ofs); + /* note, we use ascii tolower instead of system tolower, because the + * latter depends on the locale, and can lead to idname mismatch */ + memcpy(to, from, sizeof(char) * ofs); + BLI_str_tolower_ascii(to, ofs); - to[ofs] = '.'; - BLI_strncpy(to + (ofs + 1), sep + 4, OP_MAX_TYPENAME - (ofs + 1)); - } - else { - /* should not happen but support just in case */ - BLI_strncpy(to, from, OP_MAX_TYPENAME); - } + to[ofs] = '.'; + BLI_strncpy(to + (ofs + 1), sep + 4, OP_MAX_TYPENAME - (ofs + 1)); + } + else { + /* should not happen but support just in case */ + BLI_strncpy(to, from, OP_MAX_TYPENAME); + } } /* some.op -> SOME_OT_op */ void WM_operator_bl_idname(char *to, const char *from) { - if (from) { - const char *sep = strchr(from, '.'); + if (from) { + const char *sep = strchr(from, '.'); - if (sep) { - int ofs = (sep - from); + if (sep) { + int ofs = (sep - from); - memcpy(to, from, sizeof(char) * ofs); - BLI_str_toupper_ascii(to, ofs); - strcpy(to + ofs, "_OT_"); - strcpy(to + (ofs + 4), sep + 1); - } - else { - /* should not happen but support just in case */ - BLI_strncpy(to, from, OP_MAX_TYPENAME); - } - } - else { - to[0] = 0; - } + memcpy(to, from, sizeof(char) * ofs); + BLI_str_toupper_ascii(to, ofs); + strcpy(to + ofs, "_OT_"); + strcpy(to + (ofs + 4), sep + 1); + } + else { + /* should not happen but support just in case */ + BLI_strncpy(to, from, OP_MAX_TYPENAME); + } + } + else { + to[0] = 0; + } } /** * Sanity check to ensure #WM_operator_bl_idname won't fail. * \returns true when there are no problems with \a idname, otherwise report an error. */ -bool WM_operator_py_idname_ok_or_report(ReportList *reports, const char *classname, const char *idname) -{ - const char *ch = idname; - int dot = 0; - int i; - for (i = 0; *ch; i++, ch++) { - if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') { - /* pass */ - } - else if (*ch == '.') { - dot++; - } - else { - BKE_reportf(reports, RPT_ERROR, - "Registering operator class: '%s', invalid bl_idname '%s', at position %d", - classname, idname, i); - return false; - } - } - - if (i > (MAX_NAME - 3)) { - BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', " - "is too long, maximum length is %d", classname, idname, - MAX_NAME - 3); - return false; - } - - if (dot != 1) { - BKE_reportf(reports, RPT_ERROR, - "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character", - classname, idname); - return false; - } - return true; +bool WM_operator_py_idname_ok_or_report(ReportList *reports, + const char *classname, + const char *idname) +{ + const char *ch = idname; + int dot = 0; + int i; + for (i = 0; *ch; i++, ch++) { + if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') { + /* pass */ + } + else if (*ch == '.') { + dot++; + } + else { + BKE_reportf(reports, + RPT_ERROR, + "Registering operator class: '%s', invalid bl_idname '%s', at position %d", + classname, + idname, + i); + return false; + } + } + + if (i > (MAX_NAME - 3)) { + BKE_reportf(reports, + RPT_ERROR, + "Registering operator class: '%s', invalid bl_idname '%s', " + "is too long, maximum length is %d", + classname, + idname, + MAX_NAME - 3); + return false; + } + + if (dot != 1) { + BKE_reportf( + reports, + RPT_ERROR, + "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character", + classname, + idname); + return false; + } + return true; } /** @@ -210,176 +221,179 @@ bool WM_operator_py_idname_ok_or_report(ReportList *reports, const char *classna * * \note Both \a op and \a opptr may be `NULL` (\a op is only used for macro operators). */ -char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, const bool macro_args, - wmOperatorType *ot, PointerRNA *opptr) -{ - char idname_py[OP_MAX_TYPENAME]; - - /* for building the string */ - DynStr *dynstr = BLI_dynstr_new(); - char *cstring; - char *cstring_args; - - /* arbitrary, but can get huge string with stroke painting otherwise */ - int max_prop_length = 10; - - WM_operator_py_idname(idname_py, ot->idname); - BLI_dynstr_appendf(dynstr, "bpy.ops.%s(", idname_py); - - if (op && op->macro.first) { - /* Special handling for macros, else we only get default values in this case... */ - wmOperator *opm; - bool first_op = true; - - opm = macro_args ? op->macro.first : NULL; - - for (; opm; opm = opm->next) { - PointerRNA *opmptr = opm->ptr; - PointerRNA opmptr_default; - if (opmptr == NULL) { - WM_operator_properties_create_ptr(&opmptr_default, opm->type); - opmptr = &opmptr_default; - } - - cstring_args = RNA_pointer_as_string_id(C, opmptr); - if (first_op) { - BLI_dynstr_appendf(dynstr, "%s=%s", opm->type->idname, cstring_args); - first_op = false; - } - else { - BLI_dynstr_appendf(dynstr, ", %s=%s", opm->type->idname, cstring_args); - } - MEM_freeN(cstring_args); - - if (opmptr == &opmptr_default) { - WM_operator_properties_free(&opmptr_default); - } - } - } - else { - /* only to get the original props for comparisons */ - PointerRNA opptr_default; - const bool macro_args_test = ot->macro.first ? macro_args : true; - - if (opptr == NULL) { - WM_operator_properties_create_ptr(&opptr_default, ot); - opptr = &opptr_default; - } - - cstring_args = RNA_pointer_as_string_keywords(C, opptr, false, all_args, macro_args_test, max_prop_length); - BLI_dynstr_append(dynstr, cstring_args); - MEM_freeN(cstring_args); - - if (opptr == &opptr_default) { - WM_operator_properties_free(&opptr_default); - } - } - - BLI_dynstr_append(dynstr, ")"); - - cstring = BLI_dynstr_get_cstring(dynstr); - BLI_dynstr_free(dynstr); - return cstring; -} - -char *WM_operator_pystring(bContext *C, wmOperator *op, - const bool all_args, const bool macro_args) -{ - return WM_operator_pystring_ex(C, op, all_args, macro_args, op->type, op->ptr); +char *WM_operator_pystring_ex(bContext *C, + wmOperator *op, + const bool all_args, + const bool macro_args, + wmOperatorType *ot, + PointerRNA *opptr) +{ + char idname_py[OP_MAX_TYPENAME]; + + /* for building the string */ + DynStr *dynstr = BLI_dynstr_new(); + char *cstring; + char *cstring_args; + + /* arbitrary, but can get huge string with stroke painting otherwise */ + int max_prop_length = 10; + + WM_operator_py_idname(idname_py, ot->idname); + BLI_dynstr_appendf(dynstr, "bpy.ops.%s(", idname_py); + + if (op && op->macro.first) { + /* Special handling for macros, else we only get default values in this case... */ + wmOperator *opm; + bool first_op = true; + + opm = macro_args ? op->macro.first : NULL; + + for (; opm; opm = opm->next) { + PointerRNA *opmptr = opm->ptr; + PointerRNA opmptr_default; + if (opmptr == NULL) { + WM_operator_properties_create_ptr(&opmptr_default, opm->type); + opmptr = &opmptr_default; + } + + cstring_args = RNA_pointer_as_string_id(C, opmptr); + if (first_op) { + BLI_dynstr_appendf(dynstr, "%s=%s", opm->type->idname, cstring_args); + first_op = false; + } + else { + BLI_dynstr_appendf(dynstr, ", %s=%s", opm->type->idname, cstring_args); + } + MEM_freeN(cstring_args); + + if (opmptr == &opmptr_default) { + WM_operator_properties_free(&opmptr_default); + } + } + } + else { + /* only to get the original props for comparisons */ + PointerRNA opptr_default; + const bool macro_args_test = ot->macro.first ? macro_args : true; + + if (opptr == NULL) { + WM_operator_properties_create_ptr(&opptr_default, ot); + opptr = &opptr_default; + } + + cstring_args = RNA_pointer_as_string_keywords( + C, opptr, false, all_args, macro_args_test, max_prop_length); + BLI_dynstr_append(dynstr, cstring_args); + MEM_freeN(cstring_args); + + if (opptr == &opptr_default) { + WM_operator_properties_free(&opptr_default); + } + } + + BLI_dynstr_append(dynstr, ")"); + + cstring = BLI_dynstr_get_cstring(dynstr); + BLI_dynstr_free(dynstr); + return cstring; +} + +char *WM_operator_pystring(bContext *C, wmOperator *op, const bool all_args, const bool macro_args) +{ + return WM_operator_pystring_ex(C, op, all_args, macro_args, op->type, op->ptr); } - /** * \return true if the string was shortened */ bool WM_operator_pystring_abbreviate(char *str, int str_len_max) { - const int str_len = strlen(str); - const char *parens_start = strchr(str, '('); + const int str_len = strlen(str); + const char *parens_start = strchr(str, '('); - if (parens_start) { - const int parens_start_pos = parens_start - str; - const char *parens_end = strrchr(parens_start + 1, ')'); + if (parens_start) { + const int parens_start_pos = parens_start - str; + const char *parens_end = strrchr(parens_start + 1, ')'); - if (parens_end) { - const int parens_len = parens_end - parens_start; + if (parens_end) { + const int parens_len = parens_end - parens_start; - if (parens_len > str_len_max) { - const char *comma_first = strchr(parens_start, ','); + if (parens_len > str_len_max) { + const char *comma_first = strchr(parens_start, ','); - /* truncate after the first comma */ - if (comma_first) { - const char end_str[] = " ... )"; - const int end_str_len = sizeof(end_str) - 1; + /* truncate after the first comma */ + if (comma_first) { + const char end_str[] = " ... )"; + const int end_str_len = sizeof(end_str) - 1; - /* leave a place for the first argument*/ - const int new_str_len = (comma_first - parens_start) + 1; + /* leave a place for the first argument*/ + const int new_str_len = (comma_first - parens_start) + 1; - if (str_len >= new_str_len + parens_start_pos + end_str_len + 1) { - /* append " ... )" to the string after the comma */ - memcpy(str + new_str_len + parens_start_pos, end_str, end_str_len + 1); + if (str_len >= new_str_len + parens_start_pos + end_str_len + 1) { + /* append " ... )" to the string after the comma */ + memcpy(str + new_str_len + parens_start_pos, end_str, end_str_len + 1); - return true; - } - } - } - } - } + return true; + } + } + } + } + } - return false; + return false; } /* return NULL if no match is found */ #if 0 static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr) { - /* loop over all context items and do 2 checks - * - * - see if the pointer is in the context. - * - see if the pointers ID is in the context. - */ - - /* don't get from the context store since this is normally set only for the UI and not usable elsewhere */ - ListBase lb = CTX_data_dir_get_ex(C, false, true, true); - LinkData *link; - - const char *member_found = NULL; - const char *member_id = NULL; - - for (link = lb.first; link; link = link->next) { - const char *identifier = link->data; - PointerRNA ctx_item_ptr = {{0}}; // CTX_data_pointer_get(C, identifier); // XXX, this isnt working - - if (ctx_item_ptr.type == NULL) { - continue; - } - - if (ptr->id.data == ctx_item_ptr.id.data) { - if ((ptr->data == ctx_item_ptr.data) && - (ptr->type == ctx_item_ptr.type)) - { - /* found! */ - member_found = identifier; - break; - } - else if (RNA_struct_is_ID(ctx_item_ptr.type)) { - /* we found a reference to this ID, - * so fallback to it if there is no direct reference */ - member_id = identifier; - } - } - } - BLI_freelistN(&lb); - - if (member_found) { - return member_found; - } - else if (member_id) { - return member_id; - } - else { - return NULL; - } + /* loop over all context items and do 2 checks + * + * - see if the pointer is in the context. + * - see if the pointers ID is in the context. + */ + + /* don't get from the context store since this is normally set only for the UI and not usable elsewhere */ + ListBase lb = CTX_data_dir_get_ex(C, false, true, true); + LinkData *link; + + const char *member_found = NULL; + const char *member_id = NULL; + + for (link = lb.first; link; link = link->next) { + const char *identifier = link->data; + PointerRNA ctx_item_ptr = {{0}}; // CTX_data_pointer_get(C, identifier); // XXX, this isnt working + + if (ctx_item_ptr.type == NULL) { + continue; + } + + if (ptr->id.data == ctx_item_ptr.id.data) { + if ((ptr->data == ctx_item_ptr.data) && + (ptr->type == ctx_item_ptr.type)) + { + /* found! */ + member_found = identifier; + break; + } + else if (RNA_struct_is_ID(ctx_item_ptr.type)) { + /* we found a reference to this ID, + * so fallback to it if there is no direct reference */ + member_id = identifier; + } + } + } + BLI_freelistN(&lb); + + if (member_found) { + return member_found; + } + else if (member_id) { + return member_id; + } + else { + return NULL; + } } #else @@ -388,227 +402,227 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr) { - const char *member_id = NULL; - - if (ptr->id.data) { - -#define CTX_TEST_PTR_ID(C, member, idptr) \ - { \ - const char *ctx_member = member; \ - PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \ - if (ctx_item_ptr.id.data == idptr) { \ - member_id = ctx_member; \ - break; \ - } \ - } (void)0 - -#define CTX_TEST_PTR_ID_CAST(C, member, member_full, cast, idptr) \ - { \ - const char *ctx_member = member; \ - const char *ctx_member_full = member_full; \ - PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \ - if (ctx_item_ptr.id.data && cast(ctx_item_ptr.id.data) == idptr) { \ - member_id = ctx_member_full; \ - break; \ - } \ - } (void)0 - -#define CTX_TEST_PTR_DATA_TYPE(C, member, rna_type, rna_ptr, dataptr_cmp) \ - { \ - const char *ctx_member = member; \ - if (RNA_struct_is_a((ptr)->type, &(rna_type)) && (ptr)->data == (dataptr_cmp)) { \ - member_id = ctx_member; \ - break; \ - } \ - } (void)0 - -#define CTX_TEST_SPACE_TYPE(space_data_type, member_full, dataptr_cmp) \ - { \ - const char *ctx_member_full = member_full; \ - if (space_data->spacetype == space_data_type && ptr->data == dataptr_cmp) { \ - member_id = ctx_member_full; \ - break; \ - } \ - } (void)0 - - switch (GS(((ID *)ptr->id.data)->name)) { - case ID_SCE: - { - CTX_TEST_PTR_ID(C, "scene", ptr->id.data); - break; - } - case ID_OB: - { - CTX_TEST_PTR_ID(C, "object", ptr->id.data); - break; - } - /* from rna_Main_objects_new */ - case OB_DATA_SUPPORT_ID_CASE: - { -#define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data) - CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->id.data); - break; -#undef ID_CAST_OBDATA - } - case ID_MA: - { -#define ID_CAST_OBMATACT(id_pt) (give_current_material(((Object *)id_pt), ((Object *)id_pt)->actcol)) - CTX_TEST_PTR_ID_CAST(C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->id.data); - break; -#undef ID_CAST_OBMATACT - } - case ID_WO: - { -#define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world) - CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->id.data); - break; -#undef ID_CAST_SCENEWORLD - } - case ID_SCR: - { - CTX_TEST_PTR_ID(C, "screen", ptr->id.data); - - SpaceLink *space_data = CTX_wm_space_data(C); - - CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_Space, ptr, space_data); - CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_View3DOverlay, ptr, space_data); - CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_View3DShading, ptr, space_data); - CTX_TEST_PTR_DATA_TYPE(C, "area", RNA_Area, ptr, CTX_wm_area(C)); - CTX_TEST_PTR_DATA_TYPE(C, "region", RNA_Region, ptr, CTX_wm_region(C)); - - CTX_TEST_SPACE_TYPE(SPACE_IMAGE, "space_data.uv_editor", space_data); - CTX_TEST_SPACE_TYPE(SPACE_VIEW3D, "space_data.fx_settings", &(CTX_wm_view3d(C)->fx_settings)); - CTX_TEST_SPACE_TYPE(SPACE_NLA, "space_data.dopesheet", CTX_wm_space_nla(C)->ads); - CTX_TEST_SPACE_TYPE(SPACE_GRAPH, "space_data.dopesheet", CTX_wm_space_graph(C)->ads); - CTX_TEST_SPACE_TYPE(SPACE_ACTION, "space_data.dopesheet", &(CTX_wm_space_action(C)->ads)); - CTX_TEST_SPACE_TYPE(SPACE_FILE, "space_data.params", CTX_wm_space_file(C)->params); - break; - } - default: - break; - } -#undef CTX_TEST_PTR_ID -#undef CTX_TEST_PTR_ID_CAST -#undef CTX_TEST_SPACE_TYPE - } - - return member_id; + const char *member_id = NULL; + + if (ptr->id.data) { + +# define CTX_TEST_PTR_ID(C, member, idptr) \ + { \ + const char *ctx_member = member; \ + PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \ + if (ctx_item_ptr.id.data == idptr) { \ + member_id = ctx_member; \ + break; \ + } \ + } \ + (void)0 + +# define CTX_TEST_PTR_ID_CAST(C, member, member_full, cast, idptr) \ + { \ + const char *ctx_member = member; \ + const char *ctx_member_full = member_full; \ + PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \ + if (ctx_item_ptr.id.data && cast(ctx_item_ptr.id.data) == idptr) { \ + member_id = ctx_member_full; \ + break; \ + } \ + } \ + (void)0 + +# define CTX_TEST_PTR_DATA_TYPE(C, member, rna_type, rna_ptr, dataptr_cmp) \ + { \ + const char *ctx_member = member; \ + if (RNA_struct_is_a((ptr)->type, &(rna_type)) && (ptr)->data == (dataptr_cmp)) { \ + member_id = ctx_member; \ + break; \ + } \ + } \ + (void)0 + +# define CTX_TEST_SPACE_TYPE(space_data_type, member_full, dataptr_cmp) \ + { \ + const char *ctx_member_full = member_full; \ + if (space_data->spacetype == space_data_type && ptr->data == dataptr_cmp) { \ + member_id = ctx_member_full; \ + break; \ + } \ + } \ + (void)0 + + switch (GS(((ID *)ptr->id.data)->name)) { + case ID_SCE: { + CTX_TEST_PTR_ID(C, "scene", ptr->id.data); + break; + } + case ID_OB: { + CTX_TEST_PTR_ID(C, "object", ptr->id.data); + break; + } + /* from rna_Main_objects_new */ + case OB_DATA_SUPPORT_ID_CASE: { +# define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data) + CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->id.data); + break; +# undef ID_CAST_OBDATA + } + case ID_MA: { +# define ID_CAST_OBMATACT(id_pt) \ + (give_current_material(((Object *)id_pt), ((Object *)id_pt)->actcol)) + CTX_TEST_PTR_ID_CAST( + C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->id.data); + break; +# undef ID_CAST_OBMATACT + } + case ID_WO: { +# define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world) + CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->id.data); + break; +# undef ID_CAST_SCENEWORLD + } + case ID_SCR: { + CTX_TEST_PTR_ID(C, "screen", ptr->id.data); + + SpaceLink *space_data = CTX_wm_space_data(C); + + CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_Space, ptr, space_data); + CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_View3DOverlay, ptr, space_data); + CTX_TEST_PTR_DATA_TYPE(C, "space_data", RNA_View3DShading, ptr, space_data); + CTX_TEST_PTR_DATA_TYPE(C, "area", RNA_Area, ptr, CTX_wm_area(C)); + CTX_TEST_PTR_DATA_TYPE(C, "region", RNA_Region, ptr, CTX_wm_region(C)); + + CTX_TEST_SPACE_TYPE(SPACE_IMAGE, "space_data.uv_editor", space_data); + CTX_TEST_SPACE_TYPE( + SPACE_VIEW3D, "space_data.fx_settings", &(CTX_wm_view3d(C)->fx_settings)); + CTX_TEST_SPACE_TYPE(SPACE_NLA, "space_data.dopesheet", CTX_wm_space_nla(C)->ads); + CTX_TEST_SPACE_TYPE(SPACE_GRAPH, "space_data.dopesheet", CTX_wm_space_graph(C)->ads); + CTX_TEST_SPACE_TYPE(SPACE_ACTION, "space_data.dopesheet", &(CTX_wm_space_action(C)->ads)); + CTX_TEST_SPACE_TYPE(SPACE_FILE, "space_data.params", CTX_wm_space_file(C)->params); + break; + } + default: + break; + } +# undef CTX_TEST_PTR_ID +# undef CTX_TEST_PTR_ID_CAST +# undef CTX_TEST_SPACE_TYPE + } + + return member_id; } #endif -static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index) +static char *wm_prop_pystring_from_context(bContext *C, + PointerRNA *ptr, + PropertyRNA *prop, + int index) { - const char *member_id = wm_context_member_from_ptr(C, ptr); - char *ret = NULL; - if (member_id != NULL) { - char *prop_str = RNA_path_struct_property_py(ptr, prop, index); - if (prop_str) { - ret = BLI_sprintfN("bpy.context.%s.%s", member_id, prop_str); - MEM_freeN(prop_str); - } - } - return ret; + const char *member_id = wm_context_member_from_ptr(C, ptr); + char *ret = NULL; + if (member_id != NULL) { + char *prop_str = RNA_path_struct_property_py(ptr, prop, index); + if (prop_str) { + ret = BLI_sprintfN("bpy.context.%s.%s", member_id, prop_str); + MEM_freeN(prop_str); + } + } + return ret; } const char *WM_context_member_from_ptr(bContext *C, const PointerRNA *ptr) { - return wm_context_member_from_ptr(C, ptr); + return wm_context_member_from_ptr(C, ptr); } char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index) { - char *lhs, *rhs, *ret; + char *lhs, *rhs, *ret; - lhs = C ? wm_prop_pystring_from_context(C, ptr, prop, index) : NULL; + lhs = C ? wm_prop_pystring_from_context(C, ptr, prop, index) : NULL; - if (lhs == NULL) { - /* fallback to bpy.data.foo[id] if we dont find in the context */ - lhs = RNA_path_full_property_py(ptr, prop, index); - } + if (lhs == NULL) { + /* fallback to bpy.data.foo[id] if we dont find in the context */ + lhs = RNA_path_full_property_py(ptr, prop, index); + } - if (!lhs) { - return NULL; - } + if (!lhs) { + return NULL; + } - rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX); - if (!rhs) { - MEM_freeN(lhs); - return NULL; - } + rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX); + if (!rhs) { + MEM_freeN(lhs); + return NULL; + } - ret = BLI_sprintfN("%s = %s", lhs, rhs); - MEM_freeN(lhs); - MEM_freeN(rhs); - return ret; + ret = BLI_sprintfN("%s = %s", lhs, rhs); + MEM_freeN(lhs); + MEM_freeN(rhs); + return ret; } void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot) { - RNA_pointer_create(NULL, ot->srna, NULL, ptr); + RNA_pointer_create(NULL, ot->srna, NULL, ptr); } void WM_operator_properties_create(PointerRNA *ptr, const char *opstring) { - wmOperatorType *ot = WM_operatortype_find(opstring, false); + wmOperatorType *ot = WM_operatortype_find(opstring, false); - if (ot) { - WM_operator_properties_create_ptr(ptr, ot); - } - else { - RNA_pointer_create(NULL, &RNA_OperatorProperties, NULL, ptr); - } + if (ot) { + WM_operator_properties_create_ptr(ptr, ot); + } + else { + RNA_pointer_create(NULL, &RNA_OperatorProperties, NULL, ptr); + } } /* similar to the function above except its uses ID properties * used for keymaps and macros */ void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring) { - if (*properties == NULL) { - IDPropertyTemplate val = {0}; - *properties = IDP_New(IDP_GROUP, &val, "wmOpItemProp"); - } - - if (*ptr == NULL) { - *ptr = MEM_callocN(sizeof(PointerRNA), "wmOpItemPtr"); - WM_operator_properties_create(*ptr, opstring); - } + if (*properties == NULL) { + IDPropertyTemplate val = {0}; + *properties = IDP_New(IDP_GROUP, &val, "wmOpItemProp"); + } - (*ptr)->data = *properties; + if (*ptr == NULL) { + *ptr = MEM_callocN(sizeof(PointerRNA), "wmOpItemPtr"); + WM_operator_properties_create(*ptr, opstring); + } + (*ptr)->data = *properties; } void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context) { - RNA_STRUCT_BEGIN (ptr, prop) - { - switch (RNA_property_type(prop)) { - case PROP_ENUM: - if (no_context) { - RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); - } - else { - RNA_def_property_clear_flag(prop, PROP_ENUM_NO_CONTEXT); - } - break; - case PROP_POINTER: - { - StructRNA *ptype = RNA_property_pointer_type(ptr, prop); - - /* recurse into operator properties */ - if (RNA_struct_is_a(ptype, &RNA_OperatorProperties)) { - PointerRNA opptr = RNA_property_pointer_get(ptr, prop); - WM_operator_properties_sanitize(&opptr, no_context); - } - break; - } - default: - break; - } - } - RNA_STRUCT_END; + RNA_STRUCT_BEGIN (ptr, prop) { + switch (RNA_property_type(prop)) { + case PROP_ENUM: + if (no_context) { + RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); + } + else { + RNA_def_property_clear_flag(prop, PROP_ENUM_NO_CONTEXT); + } + break; + case PROP_POINTER: { + StructRNA *ptype = RNA_property_pointer_type(ptr, prop); + + /* recurse into operator properties */ + if (RNA_struct_is_a(ptype, &RNA_OperatorProperties)) { + PointerRNA opptr = RNA_property_pointer_get(ptr, prop); + WM_operator_properties_sanitize(&opptr, no_context); + } + break; + } + default: + break; + } + } + RNA_STRUCT_END; } - /** set all props to their default, * \param do_update: Only update un-initialized props. * @@ -617,339 +631,362 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context) */ bool WM_operator_properties_default(PointerRNA *ptr, const bool do_update) { - bool changed = false; - RNA_STRUCT_BEGIN (ptr, prop) - { - switch (RNA_property_type(prop)) { - case PROP_POINTER: - { - StructRNA *ptype = RNA_property_pointer_type(ptr, prop); - if (ptype != &RNA_Struct) { - PointerRNA opptr = RNA_property_pointer_get(ptr, prop); - changed |= WM_operator_properties_default(&opptr, do_update); - } - break; - } - default: - if ((do_update == false) || (RNA_property_is_set(ptr, prop) == false)) { - if (RNA_property_reset(ptr, prop, -1)) { - changed = true; - } - } - break; - } - } - RNA_STRUCT_END; - - return changed; + bool changed = false; + RNA_STRUCT_BEGIN (ptr, prop) { + switch (RNA_property_type(prop)) { + case PROP_POINTER: { + StructRNA *ptype = RNA_property_pointer_type(ptr, prop); + if (ptype != &RNA_Struct) { + PointerRNA opptr = RNA_property_pointer_get(ptr, prop); + changed |= WM_operator_properties_default(&opptr, do_update); + } + break; + } + default: + if ((do_update == false) || (RNA_property_is_set(ptr, prop) == false)) { + if (RNA_property_reset(ptr, prop, -1)) { + changed = true; + } + } + break; + } + } + RNA_STRUCT_END; + + return changed; } /* remove all props without PROP_SKIP_SAVE */ void WM_operator_properties_reset(wmOperator *op) { - if (op->ptr->data) { - PropertyRNA *iterprop; - iterprop = RNA_struct_iterator_property(op->type->srna); + if (op->ptr->data) { + PropertyRNA *iterprop; + iterprop = RNA_struct_iterator_property(op->type->srna); - RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) - { - PropertyRNA *prop = itemptr.data; + RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) { + PropertyRNA *prop = itemptr.data; - if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) { - const char *identifier = RNA_property_identifier(prop); - RNA_struct_idprops_unset(op->ptr, identifier); - } - } - RNA_PROP_END; - } + if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) { + const char *identifier = RNA_property_identifier(prop); + RNA_struct_idprops_unset(op->ptr, identifier); + } + } + RNA_PROP_END; + } } void WM_operator_properties_clear(PointerRNA *ptr) { - IDProperty *properties = ptr->data; + IDProperty *properties = ptr->data; - if (properties) { - IDP_ClearProperty(properties); - } + if (properties) { + IDP_ClearProperty(properties); + } } void WM_operator_properties_free(PointerRNA *ptr) { - IDProperty *properties = ptr->data; + IDProperty *properties = ptr->data; - if (properties) { - IDP_FreeProperty(properties); - MEM_freeN(properties); - ptr->data = NULL; /* just in case */ - } + if (properties) { + IDP_FreeProperty(properties); + MEM_freeN(properties); + ptr->data = NULL; /* just in case */ + } } /* ************ default op callbacks, exported *********** */ void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op) { - if (op->flag & OP_IS_INVOKE) { - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - - const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL); - - /* always run, so the values are initialized, - * otherwise we may get differ behavior when (dia != 1.0) */ - RNA_STRUCT_BEGIN (op->ptr, prop) - { - if (RNA_property_type(prop) == PROP_FLOAT) { - PropertySubType pstype = RNA_property_subtype(prop); - if (pstype == PROP_DISTANCE) { - /* we don't support arrays yet */ - BLI_assert(RNA_property_array_check(prop) == false); - /* initialize */ - if (!RNA_property_is_set_ex(op->ptr, prop, false)) { - const float value = RNA_property_float_get_default(op->ptr, prop) * dia; - RNA_property_float_set(op->ptr, prop, value); - } - } - } - } - RNA_STRUCT_END; - } + if (op->flag & OP_IS_INVOKE) { + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + + const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : + ED_scene_grid_scale(scene, NULL); + + /* always run, so the values are initialized, + * otherwise we may get differ behavior when (dia != 1.0) */ + RNA_STRUCT_BEGIN (op->ptr, prop) { + if (RNA_property_type(prop) == PROP_FLOAT) { + PropertySubType pstype = RNA_property_subtype(prop); + if (pstype == PROP_DISTANCE) { + /* we don't support arrays yet */ + BLI_assert(RNA_property_array_check(prop) == false); + /* initialize */ + if (!RNA_property_is_set_ex(op->ptr, prop, false)) { + const float value = RNA_property_float_get_default(op->ptr, prop) * dia; + RNA_property_float_set(op->ptr, prop, value); + } + } + } + } + RNA_STRUCT_END; + } } int WM_operator_smooth_viewtx_get(const wmOperator *op) { - return (op->flag & OP_IS_INVOKE) ? U.smooth_viewtx : 0; + return (op->flag & OP_IS_INVOKE) ? U.smooth_viewtx : 0; } /* invoke callback, uses enum property named "type" */ int WM_menu_invoke_ex(bContext *C, wmOperator *op, int opcontext) { - PropertyRNA *prop = op->type->prop; - uiPopupMenu *pup; - uiLayout *layout; - - if (prop == NULL) { - CLOG_ERROR(WM_LOG_OPERATORS, - "'%s' has no enum property set", - op->type->idname); - } - else if (RNA_property_type(prop) != PROP_ENUM) { - CLOG_ERROR(WM_LOG_OPERATORS, - "'%s', '%s' is not an enum property", - op->type->idname, RNA_property_identifier(prop)); - } - else if (RNA_property_is_set(op->ptr, prop)) { - const int retval = op->type->exec(C, op); - OPERATOR_RETVAL_CHECK(retval); - return retval; - } - else { - pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE); - layout = UI_popup_menu_layout(pup); - /* set this so the default execution context is the same as submenus */ - uiLayoutSetOperatorContext(layout, opcontext); - uiItemsFullEnumO(layout, op->type->idname, RNA_property_identifier(prop), op->ptr->data, opcontext, 0); - UI_popup_menu_end(C, pup); - return OPERATOR_INTERFACE; - } - - return OPERATOR_CANCELLED; + PropertyRNA *prop = op->type->prop; + uiPopupMenu *pup; + uiLayout *layout; + + if (prop == NULL) { + CLOG_ERROR(WM_LOG_OPERATORS, "'%s' has no enum property set", op->type->idname); + } + else if (RNA_property_type(prop) != PROP_ENUM) { + CLOG_ERROR(WM_LOG_OPERATORS, + "'%s', '%s' is not an enum property", + op->type->idname, + RNA_property_identifier(prop)); + } + else if (RNA_property_is_set(op->ptr, prop)) { + const int retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + return retval; + } + else { + pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE); + layout = UI_popup_menu_layout(pup); + /* set this so the default execution context is the same as submenus */ + uiLayoutSetOperatorContext(layout, opcontext); + uiItemsFullEnumO( + layout, op->type->idname, RNA_property_identifier(prop), op->ptr->data, opcontext, 0); + UI_popup_menu_end(C, pup); + return OPERATOR_INTERFACE; + } + + return OPERATOR_CANCELLED; } int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_REGION_WIN); + return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_REGION_WIN); } struct EnumSearchMenu { - wmOperator *op; /* the operator that will be executed when selecting an item */ + wmOperator *op; /* the operator that will be executed when selecting an item */ - bool use_previews; - short prv_cols, prv_rows; + bool use_previews; + short prv_cols, prv_rows; }; /* generic enum search invoke popup */ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg) { - struct EnumSearchMenu *search_menu = arg; - wmWindow *win = CTX_wm_window(C); - wmOperator *op = search_menu->op; - /* template_ID uses 4 * widget_unit for width, we use a bit more, some items may have a suffix to show */ - const int width = search_menu->use_previews ? 5 * U.widget_unit * search_menu->prv_cols : UI_searchbox_size_x(); - const int height = search_menu->use_previews ? 5 * U.widget_unit * search_menu->prv_rows : UI_searchbox_size_y(); - static char search[256] = ""; - uiBlock *block; - uiBut *but; - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); - UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); - - search[0] = '\0'; - BLI_assert(search_menu->use_previews || (search_menu->prv_cols == 0 && search_menu->prv_rows == 0)); + struct EnumSearchMenu *search_menu = arg; + wmWindow *win = CTX_wm_window(C); + wmOperator *op = search_menu->op; + /* template_ID uses 4 * widget_unit for width, we use a bit more, some items may have a suffix to show */ + const int width = search_menu->use_previews ? 5 * U.widget_unit * search_menu->prv_cols : + UI_searchbox_size_x(); + const int height = search_menu->use_previews ? 5 * U.widget_unit * search_menu->prv_rows : + UI_searchbox_size_y(); + static char search[256] = ""; + uiBlock *block; + uiBut *but; + + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); + UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); + + search[0] = '\0'; + BLI_assert(search_menu->use_previews || + (search_menu->prv_cols == 0 && search_menu->prv_rows == 0)); #if 0 /* ok, this isn't so easy... */ - uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); #endif - but = uiDefSearchButO_ptr(block, op->type, op->ptr->data, search, 0, ICON_VIEWZOOM, sizeof(search), - 10, 10, width, UI_UNIT_Y, search_menu->prv_rows, search_menu->prv_cols, ""); - - /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), width, height, NULL, 0, 0, 0, 0, NULL); - - /* Move it downwards, mouse over button. */ - UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y}); - - UI_but_focus_on_enter_event(win, but); - - return block; + but = uiDefSearchButO_ptr(block, + op->type, + op->ptr->data, + search, + 0, + ICON_VIEWZOOM, + sizeof(search), + 10, + 10, + width, + UI_UNIT_Y, + search_menu->prv_rows, + search_menu->prv_cols, + ""); + + /* fake button, it holds space for search items */ + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + "", + 10, + 10 - UI_searchbox_size_y(), + width, + height, + NULL, + 0, + 0, + 0, + 0, + NULL); + + /* Move it downwards, mouse over button. */ + UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y}); + + UI_but_focus_on_enter_event(win, but); + + return block; } /** * Similar to #WM_enum_search_invoke, but draws previews. Also, this can't * be used as invoke callback directly since it needs additional info. */ -int WM_enum_search_invoke_previews( - bContext *C, wmOperator *op, short prv_cols, short prv_rows) +int WM_enum_search_invoke_previews(bContext *C, wmOperator *op, short prv_cols, short prv_rows) { - static struct EnumSearchMenu search_menu; + static struct EnumSearchMenu search_menu; - search_menu.op = op; - search_menu.use_previews = true; - search_menu.prv_cols = prv_cols; - search_menu.prv_rows = prv_rows; + search_menu.op = op; + search_menu.use_previews = true; + search_menu.prv_cols = prv_cols; + search_menu.prv_rows = prv_rows; - UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu); + UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu); - return OPERATOR_INTERFACE; + return OPERATOR_INTERFACE; } int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - static struct EnumSearchMenu search_menu; - search_menu.op = op; - UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu); - return OPERATOR_INTERFACE; + static struct EnumSearchMenu search_menu; + search_menu.op = op; + UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu); + return OPERATOR_INTERFACE; } /* Can't be used as an invoke directly, needs message arg (can be NULL) */ -int WM_operator_confirm_message_ex(bContext *C, wmOperator *op, - const char *title, const int icon, - const char *message) +int WM_operator_confirm_message_ex( + bContext *C, wmOperator *op, const char *title, const int icon, const char *message) { - uiPopupMenu *pup; - uiLayout *layout; - IDProperty *properties = op->ptr->data; + uiPopupMenu *pup; + uiLayout *layout; + IDProperty *properties = op->ptr->data; - if (properties && properties->len) { - properties = IDP_CopyProperty(op->ptr->data); - } - else { - properties = NULL; - } + if (properties && properties->len) { + properties = IDP_CopyProperty(op->ptr->data); + } + else { + properties = NULL; + } - pup = UI_popup_menu_begin(C, title, icon); - layout = UI_popup_menu_layout(pup); - uiItemFullO_ptr(layout, op->type, message, ICON_NONE, properties, WM_OP_EXEC_REGION_WIN, 0, NULL); - UI_popup_menu_end(C, pup); + pup = UI_popup_menu_begin(C, title, icon); + layout = UI_popup_menu_layout(pup); + uiItemFullO_ptr( + layout, op->type, message, ICON_NONE, properties, WM_OP_EXEC_REGION_WIN, 0, NULL); + UI_popup_menu_end(C, pup); - return OPERATOR_INTERFACE; + return OPERATOR_INTERFACE; } int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message) { - return WM_operator_confirm_message_ex(C, op, IFACE_("OK?"), ICON_QUESTION, message); + return WM_operator_confirm_message_ex(C, op, IFACE_("OK?"), ICON_QUESTION, message); } int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return WM_operator_confirm_message(C, op, NULL); + return WM_operator_confirm_message(C, op, NULL); } int WM_operator_confirm_or_exec(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - const bool confirm = RNA_boolean_get(op->ptr, "confirm"); - if (confirm) { - return WM_operator_confirm_message(C, op, NULL); - } - else { - return op->type->exec(C, op); - } + const bool confirm = RNA_boolean_get(op->ptr, "confirm"); + if (confirm) { + return WM_operator_confirm_message(C, op, NULL); + } + else { + return op->type->exec(C, op); + } } - /* op->invoke, opens fileselect if path property not set, otherwise executes */ int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (RNA_struct_property_is_set(op->ptr, "filepath")) { - return WM_operator_call_notest(C, op); /* call exec direct */ - } - else { - WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; - } + if (RNA_struct_property_is_set(op->ptr, "filepath")) { + return WM_operator_call_notest(C, op); /* call exec direct */ + } + else { + WM_event_add_fileselect(C, op); + return OPERATOR_RUNNING_MODAL; + } } bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format) { - PropertyRNA *prop; - char filepath[FILE_MAX]; - /* dont NULL check prop, this can only run on ops with a 'filepath' */ - prop = RNA_struct_find_property(op->ptr, "filepath"); - RNA_property_string_get(op->ptr, prop, filepath); - if (BKE_image_path_ensure_ext_from_imformat(filepath, im_format)) { - RNA_property_string_set(op->ptr, prop, filepath); - /* note, we could check for and update 'filename' here, - * but so far nothing needs this. */ - return true; - } - return false; + PropertyRNA *prop; + char filepath[FILE_MAX]; + /* dont NULL check prop, this can only run on ops with a 'filepath' */ + prop = RNA_struct_find_property(op->ptr, "filepath"); + RNA_property_string_get(op->ptr, prop, filepath); + if (BKE_image_path_ensure_ext_from_imformat(filepath, im_format)) { + RNA_property_string_set(op->ptr, prop, filepath); + /* note, we could check for and update 'filename' here, + * but so far nothing needs this. */ + return true; + } + return false; } /* op->poll */ bool WM_operator_winactive(bContext *C) { - if (CTX_wm_window(C) == NULL) { - return 0; - } - return 1; + if (CTX_wm_window(C) == NULL) { + return 0; + } + return 1; } /* return false, if the UI should be disabled */ bool WM_operator_check_ui_enabled(const bContext *C, const char *idname) { - wmWindowManager *wm = CTX_wm_manager(C); - Scene *scene = CTX_data_scene(C); + wmWindowManager *wm = CTX_wm_manager(C); + Scene *scene = CTX_data_scene(C); - return !((ED_undo_is_valid(C, idname) == false) || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)); + return !((ED_undo_is_valid(C, idname) == false) || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)); } wmOperator *WM_operator_last_redo(const bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - wmOperator *op; + 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; - } - } + /* 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; + return op; } IDProperty *WM_operator_last_properties_ensure_idprops(wmOperatorType *ot) { - if (ot->last_properties == NULL) { - IDPropertyTemplate val = {0}; - ot->last_properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); - } - return ot->last_properties; + if (ot->last_properties == NULL) { + IDPropertyTemplate val = {0}; + ot->last_properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); + } + return ot->last_properties; } void WM_operator_last_properties_ensure(wmOperatorType *ot, PointerRNA *ptr) { - IDProperty *props = WM_operator_last_properties_ensure_idprops(ot); - RNA_pointer_create(NULL, ot->srna, props, ptr); + IDProperty *props = WM_operator_last_properties_ensure_idprops(ot); + RNA_pointer_create(NULL, ot->srna, props, ptr); } /** @@ -957,327 +994,336 @@ void WM_operator_last_properties_ensure(wmOperatorType *ot, PointerRNA *ptr) */ ID *WM_operator_drop_load_path(struct bContext *C, wmOperator *op, const short idcode) { - Main *bmain = CTX_data_main(C); - ID *id = NULL; - /* check input variables */ - if (RNA_struct_property_is_set(op->ptr, "filepath")) { - const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); - char path[FILE_MAX]; - bool exists = false; - - RNA_string_get(op->ptr, "filepath", path); - - errno = 0; - - if (idcode == ID_IM) { - id = (ID *)BKE_image_load_exists_ex(bmain, path, &exists); - } - else { - BLI_assert(0); - } - - if (!id) { - BKE_reportf(op->reports, RPT_ERROR, "Cannot read %s '%s': %s", - BKE_idcode_to_name(idcode), path, - errno ? strerror(errno) : TIP_("unsupported format")); - return NULL; - } - - if (is_relative_path ) { - if (exists == false) { - if (idcode == ID_IM) { - BLI_path_rel(((Image *)id)->name, BKE_main_blendfile_path(bmain)); - } - else { - BLI_assert(0); - } - } - } - } - else if (RNA_struct_property_is_set(op->ptr, "name")) { - char name[MAX_ID_NAME - 2]; - RNA_string_get(op->ptr, "name", name); - id = BKE_libblock_find_name(bmain, idcode, name); - if (!id) { - BKE_reportf(op->reports, RPT_ERROR, "%s '%s' not found", - BKE_idcode_to_name(idcode), name); - return NULL; - } - id_us_plus(id); - } - - return id; + Main *bmain = CTX_data_main(C); + ID *id = NULL; + /* check input variables */ + if (RNA_struct_property_is_set(op->ptr, "filepath")) { + const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); + char path[FILE_MAX]; + bool exists = false; + + RNA_string_get(op->ptr, "filepath", path); + + errno = 0; + + if (idcode == ID_IM) { + id = (ID *)BKE_image_load_exists_ex(bmain, path, &exists); + } + else { + BLI_assert(0); + } + + if (!id) { + BKE_reportf(op->reports, + RPT_ERROR, + "Cannot read %s '%s': %s", + BKE_idcode_to_name(idcode), + path, + errno ? strerror(errno) : TIP_("unsupported format")); + return NULL; + } + + if (is_relative_path) { + if (exists == false) { + if (idcode == ID_IM) { + BLI_path_rel(((Image *)id)->name, BKE_main_blendfile_path(bmain)); + } + else { + BLI_assert(0); + } + } + } + } + else if (RNA_struct_property_is_set(op->ptr, "name")) { + char name[MAX_ID_NAME - 2]; + RNA_string_get(op->ptr, "name", name); + id = BKE_libblock_find_name(bmain, idcode, name); + if (!id) { + BKE_reportf(op->reports, RPT_ERROR, "%s '%s' not found", BKE_idcode_to_name(idcode), name); + return NULL; + } + id_us_plus(id); + } + + return id; } static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event)) { - wmOperator *op = arg_op; + wmOperator *op = arg_op; - if (op == WM_operator_last_redo(C)) { - /* operator was already executed once? undo & repeat */ - ED_undo_operator_repeat(C, op); - } - else { - /* operator not executed yet, call it */ - ED_undo_push_op(C, op); - wm_operator_register(C, op); + if (op == WM_operator_last_redo(C)) { + /* operator was already executed once? undo & repeat */ + ED_undo_operator_repeat(C, op); + } + else { + /* operator not executed yet, call it */ + ED_undo_push_op(C, op); + wm_operator_register(C, op); - WM_operator_repeat(C, op); - } + WM_operator_repeat(C, op); + } } static void wm_block_redo_cancel_cb(bContext *C, void *arg_op) { - wmOperator *op = arg_op; + wmOperator *op = arg_op; - /* if operator never got executed, free it */ - if (op != WM_operator_last_redo(C)) { - WM_operator_free(op); - } + /* if operator never got executed, free it */ + if (op != WM_operator_last_redo(C)) { + WM_operator_free(op); + } } static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) { - wmOperator *op = arg_op; - uiBlock *block; - uiLayout *layout; - uiStyle *style = UI_style_get(); - int width = 15 * UI_UNIT_X; - - block = UI_block_begin(C, ar, __func__, UI_EMBOSS); - UI_block_flag_disable(block, UI_BLOCK_LOOP); - UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR); - - /* UI_BLOCK_NUMSELECT for layer buttons */ - UI_block_flag_enable(block, UI_BLOCK_NUMSELECT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT); - - /* if register is not enabled, the operator gets freed on OPERATOR_FINISHED - * ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */ - assert(op->type->flag & OPTYPE_REGISTER); - - UI_block_func_handle_set(block, wm_block_redo_cb, arg_op); - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, 0, style); - - if (op == WM_operator_last_redo(C)) { - if (!WM_operator_check_ui_enabled(C, op->type->name)) { - uiLayoutSetEnabled(layout, false); - } - } - - if (op->type->flag & OPTYPE_MACRO) { - for (op = op->macro.first; op; op = op->next) { - uiTemplateOperatorPropertyButs( - C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, - UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - if (op->next) { - uiItemS(layout); - } - } - } - else { - uiTemplateOperatorPropertyButs( - C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, - UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - } - - UI_block_bounds_set_popup(block, 4, NULL); - - return block; + wmOperator *op = arg_op; + uiBlock *block; + uiLayout *layout; + uiStyle *style = UI_style_get(); + int width = 15 * UI_UNIT_X; + + block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + UI_block_flag_disable(block, UI_BLOCK_LOOP); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR); + + /* UI_BLOCK_NUMSELECT for layer buttons */ + UI_block_flag_enable(block, UI_BLOCK_NUMSELECT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT); + + /* if register is not enabled, the operator gets freed on OPERATOR_FINISHED + * ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */ + assert(op->type->flag & OPTYPE_REGISTER); + + UI_block_func_handle_set(block, wm_block_redo_cb, arg_op); + layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, 0, style); + + if (op == WM_operator_last_redo(C)) { + if (!WM_operator_check_ui_enabled(C, op->type->name)) { + uiLayoutSetEnabled(layout, false); + } + } + + if (op->type->flag & OPTYPE_MACRO) { + for (op = op->macro.first; op; op = op->next) { + uiTemplateOperatorPropertyButs( + C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); + if (op->next) { + uiItemS(layout); + } + } + } + else { + uiTemplateOperatorPropertyButs( + C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); + } + + UI_block_bounds_set_popup(block, 4, NULL); + + return block; } typedef struct wmOpPopUp { - wmOperator *op; - int width; - int height; - int free_op; + 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) { - wmOpPopUp *data = arg1; - uiBlock *block = arg2; + wmOpPopUp *data = arg1; + uiBlock *block = arg2; - /* Explicitly set UI_RETURN_OK flag, otherwise the menu might be canceled - * in case WM_operator_call_ex exits/reloads the current file (T49199). */ - UI_popup_menu_retval_set(block, UI_RETURN_OK, true); + /* Explicitly set UI_RETURN_OK flag, otherwise the menu might be canceled + * in case WM_operator_call_ex exits/reloads the current file (T49199). */ + UI_popup_menu_retval_set(block, UI_RETURN_OK, true); - WM_operator_call_ex(C, data->op, true); + WM_operator_call_ex(C, data->op, true); - /* let execute handle freeing it */ - //data->free_op = false; - //data->op = NULL; + /* 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); + /* in this case, wm_operator_ui_popup_cancel wont run */ + MEM_freeN(data); - /* get context data *after* WM_operator_call_ex which might have closed the current file and changed context */ - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); + /* get context data *after* WM_operator_call_ex which might have closed the current file and changed context */ + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); - /* check window before 'block->handle' incase the - * popup execution closed the window and freed the block. see T44688. - */ - /* Post 2.78 TODO: Check if this fix and others related to T44688 are still - * needed or can be improved now that requesting context data has been corrected - * (see above). We're close to release so not a good time for experiments. - * -- Julian - */ - if (BLI_findindex(&wm->windows, win) != -1) { - UI_popup_block_close(C, win, block); - } + /* check window before 'block->handle' incase the + * popup execution closed the window and freed the block. see T44688. + */ + /* Post 2.78 TODO: Check if this fix and others related to T44688 are still + * needed or can be improved now that requesting context data has been corrected + * (see above). We're close to release so not a good time for experiments. + * -- Julian + */ + if (BLI_findindex(&wm->windows, win) != -1) { + UI_popup_block_close(C, win, block); + } } /* Dialogs are popups that require user verification (click OK) before exec */ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData) { - wmOpPopUp *data = userData; - wmOperator *op = data->op; - uiBlock *block; - uiLayout *layout; - uiStyle *style = UI_style_get(); + wmOpPopUp *data = userData; + wmOperator *op = data->op; + uiBlock *block; + uiLayout *layout; + uiStyle *style = UI_style_get(); - block = UI_block_begin(C, ar, __func__, UI_EMBOSS); - UI_block_flag_disable(block, UI_BLOCK_LOOP); - UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR); + block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + UI_block_flag_disable(block, UI_BLOCK_LOOP); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR); - /* intentionally don't use 'UI_BLOCK_MOVEMOUSE_QUIT', some dialogues have many items - * where quitting by accident is very annoying */ - UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NUMSELECT); + /* intentionally don't use 'UI_BLOCK_MOVEMOUSE_QUIT', some dialogues have many items + * where quitting by accident is very annoying */ + UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NUMSELECT); - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style); + layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style); - uiTemplateOperatorPropertyButs( - C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, - UI_TEMPLATE_OP_PROPS_SHOW_TITLE); + uiTemplateOperatorPropertyButs( + C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - /* clear so the OK button is left alone */ - UI_block_func_set(block, NULL, NULL, NULL); + /* clear so the OK button is left alone */ + UI_block_func_set(block, NULL, NULL, NULL); - /* new column so as not to interfere with custom layouts [#26436] */ - { - uiBlock *col_block; - uiLayout *col; - uiBut *btn; + /* new column so as not to interfere with custom layouts [#26436] */ + { + uiBlock *col_block; + uiLayout *col; + uiBut *btn; - col = uiLayoutColumn(layout, false); - col_block = uiLayoutGetBlock(col); - /* Create OK button, the callback of which will execute op */ - btn = uiDefBut(col_block, UI_BTYPE_BUT, 0, IFACE_("OK"), 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - UI_but_flag_enable(btn, UI_BUT_ACTIVE_DEFAULT); - UI_but_func_set(btn, dialog_exec_cb, data, col_block); - } + col = uiLayoutColumn(layout, false); + col_block = uiLayoutGetBlock(col); + /* Create OK button, the callback of which will execute op */ + btn = uiDefBut( + col_block, UI_BTYPE_BUT, 0, IFACE_("OK"), 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_flag_enable(btn, UI_BUT_ACTIVE_DEFAULT); + UI_but_func_set(btn, dialog_exec_cb, data, col_block); + } - /* center around the mouse */ - UI_block_bounds_set_popup(block, 4, (const int[2]){data->width / -2, data->height / 2}); + /* center around the mouse */ + UI_block_bounds_set_popup(block, 4, (const int[2]){data->width / -2, data->height / 2}); - UI_block_active_only_flagged_buttons(C, ar, block); + UI_block_active_only_flagged_buttons(C, ar, block); - return block; + return block; } static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData) { - wmOpPopUp *data = userData; - wmOperator *op = data->op; - uiBlock *block; - uiLayout *layout; - uiStyle *style = UI_style_get(); + wmOpPopUp *data = userData; + wmOperator *op = data->op; + uiBlock *block; + uiLayout *layout; + uiStyle *style = UI_style_get(); - block = UI_block_begin(C, ar, __func__, UI_EMBOSS); - UI_block_flag_disable(block, UI_BLOCK_LOOP); - UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT); - UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR); + block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + UI_block_flag_disable(block, UI_BLOCK_LOOP); + UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR); - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style); + layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style); - /* since ui is defined the auto-layout args are not used */ - uiTemplateOperatorPropertyButs(C, layout, op, UI_BUT_LABEL_ALIGN_COLUMN, 0); + /* since ui is defined the auto-layout args are not used */ + uiTemplateOperatorPropertyButs(C, layout, op, UI_BUT_LABEL_ALIGN_COLUMN, 0); - UI_block_func_set(block, NULL, NULL, NULL); + UI_block_func_set(block, NULL, NULL, NULL); - UI_block_bounds_set_popup(block, 4, NULL); + UI_block_bounds_set_popup(block, 4, NULL); - UI_block_active_only_flagged_buttons(C, ar, block); + UI_block_active_only_flagged_buttons(C, ar, block); - return block; + return block; } static void wm_operator_ui_popup_cancel(struct bContext *C, void *userData) { - wmOpPopUp *data = userData; - wmOperator *op = data->op; + wmOpPopUp *data = userData; + wmOperator *op = data->op; - if (op) { - if (op->type->cancel) { - op->type->cancel(C, op); - } + if (op) { + if (op->type->cancel) { + op->type->cancel(C, op); + } - if (data->free_op) { - WM_operator_free(op); - } - } + if (data->free_op) { + WM_operator_free(op); + } + } - MEM_freeN(data); + MEM_freeN(data); } static void wm_operator_ui_popup_ok(struct bContext *C, void *arg, int retval) { - wmOpPopUp *data = arg; - wmOperator *op = data->op; + wmOpPopUp *data = arg; + wmOperator *op = data->op; - if (op && retval > 0) { - WM_operator_call_ex(C, op, true); - } + if (op && retval > 0) { + WM_operator_call_ex(C, op, true); + } - MEM_freeN(data); + 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 * U.dpi_fac; - data->height = height * U.dpi_fac; - data->free_op = true; /* if this runs and gets registered we may want not to free it */ - UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data, op); - return OPERATOR_RUNNING_MODAL; + wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_ui_popup"); + data->op = op; + data->width = width * U.dpi_fac; + data->height = height * U.dpi_fac; + data->free_op = true; /* if this runs and gets registered we may want not to free it */ + UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data, op); + return OPERATOR_RUNNING_MODAL; } /** * For use by #WM_operator_props_popup_call, #WM_operator_props_popup only. * * \note operator menu needs undo flag enabled, for redo callback */ -static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, - const bool do_call, const bool do_redo) -{ - if ((op->type->flag & OPTYPE_REGISTER) == 0) { - BKE_reportf(op->reports, RPT_ERROR, - "Operator '%s' does not have register enabled, incorrect invoke function", op->type->idname); - return OPERATOR_CANCELLED; - } - - if (do_redo) { - if ((op->type->flag & OPTYPE_UNDO) == 0) { - BKE_reportf(op->reports, RPT_ERROR, - "Operator '%s' does not have undo enabled, incorrect invoke function", op->type->idname); - return OPERATOR_CANCELLED; - } - } - - /* if we don't have global undo, we can't do undo push for automatic redo, - * so we require manual OK clicking in this popup */ - if (!do_redo || !(U.uiflag & USER_GLOBALUNDO)) { - return WM_operator_props_dialog_popup(C, op, 300, 20); - } - - UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op, op); - - if (do_call) { - wm_block_redo_cb(C, op, 0); - } - - return OPERATOR_RUNNING_MODAL; +static int wm_operator_props_popup_ex(bContext *C, + wmOperator *op, + const bool do_call, + const bool do_redo) +{ + if ((op->type->flag & OPTYPE_REGISTER) == 0) { + BKE_reportf(op->reports, + RPT_ERROR, + "Operator '%s' does not have register enabled, incorrect invoke function", + op->type->idname); + return OPERATOR_CANCELLED; + } + + if (do_redo) { + if ((op->type->flag & OPTYPE_UNDO) == 0) { + BKE_reportf(op->reports, + RPT_ERROR, + "Operator '%s' does not have undo enabled, incorrect invoke function", + op->type->idname); + return OPERATOR_CANCELLED; + } + } + + /* if we don't have global undo, we can't do undo push for automatic redo, + * so we require manual OK clicking in this popup */ + if (!do_redo || !(U.uiflag & USER_GLOBALUNDO)) { + return WM_operator_props_dialog_popup(C, op, 300, 20); + } + + UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op, op); + + if (do_call) { + wm_block_redo_cb(C, op, 0); + } + + return OPERATOR_RUNNING_MODAL; } /** @@ -1286,7 +1332,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, */ int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return wm_operator_props_popup_ex(C, op, false, false); + return wm_operator_props_popup_ex(C, op, false, false); } /** @@ -1296,471 +1342,559 @@ int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent * */ int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return wm_operator_props_popup_ex(C, op, true, true); + return wm_operator_props_popup_ex(C, op, true, true); } int WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return wm_operator_props_popup_ex(C, op, false, true); + return wm_operator_props_popup_ex(C, op, false, true); } int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int height) { - wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup"); + wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup"); - data->op = op; - data->width = width * U.dpi_fac; - data->height = height * U.dpi_fac; - data->free_op = true; /* if this runs and gets registered we may want not to free it */ + data->op = op; + data->width = width * U.dpi_fac; + data->height = height * U.dpi_fac; + 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 */ - UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op); + /* op is not executed until popup OK but is clicked */ + UI_popup_block_ex( + C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op); - return OPERATOR_RUNNING_MODAL; + 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 */ - if ((op->type->flag & OPTYPE_REGISTER) == 0) { - BKE_reportf(CTX_wm_reports(C), RPT_ERROR, - "Operator redo '%s' does not have register enabled, incorrect invoke function", op->type->idname); - return OPERATOR_CANCELLED; - } - if (op->type->poll && op->type->poll(C) == 0) { - BKE_reportf(CTX_wm_reports(C), RPT_ERROR, "Operator redo '%s': wrong context", op->type->idname); - return OPERATOR_CANCELLED; - } + /* CTX_wm_reports(C) because operator is on stack, not active in event system */ + if ((op->type->flag & OPTYPE_REGISTER) == 0) { + BKE_reportf(CTX_wm_reports(C), + RPT_ERROR, + "Operator redo '%s' does not have register enabled, incorrect invoke function", + op->type->idname); + return OPERATOR_CANCELLED; + } + if (op->type->poll && op->type->poll(C) == 0) { + BKE_reportf( + CTX_wm_reports(C), RPT_ERROR, "Operator redo '%s': wrong context", op->type->idname); + return OPERATOR_CANCELLED; + } - UI_popup_block_invoke(C, wm_block_create_redo, op); + UI_popup_block_invoke(C, wm_block_create_redo, op); - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } /* ***************** Debug menu ************************* */ static int wm_debug_menu_exec(bContext *C, wmOperator *op) { - G.debug_value = RNA_int_get(op->ptr, "debug_value"); - ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C)); - WM_event_add_notifier(C, NC_WINDOW, NULL); + G.debug_value = RNA_int_get(op->ptr, "debug_value"); + ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C)); + WM_event_add_notifier(C, NC_WINDOW, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int wm_debug_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - RNA_int_set(op->ptr, "debug_value", G.debug_value); - return WM_operator_props_dialog_popup(C, op, 180, 20); + RNA_int_set(op->ptr, "debug_value", G.debug_value); + return WM_operator_props_dialog_popup(C, op, 180, 20); } static void WM_OT_debug_menu(wmOperatorType *ot) { - ot->name = "Debug Menu"; - ot->idname = "WM_OT_debug_menu"; - ot->description = "Open a popup to set the debug level"; + ot->name = "Debug Menu"; + ot->idname = "WM_OT_debug_menu"; + ot->description = "Open a popup to set the debug level"; - ot->invoke = wm_debug_menu_invoke; - ot->exec = wm_debug_menu_exec; - ot->poll = WM_operator_winactive; + ot->invoke = wm_debug_menu_invoke; + ot->exec = wm_debug_menu_exec; + ot->poll = WM_operator_winactive; - RNA_def_int(ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000); + RNA_def_int(ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000); } /* ***************** Operator defaults ************************* */ static int wm_operator_defaults_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "active_operator", &RNA_Operator); + PointerRNA ptr = CTX_data_pointer_get_type(C, "active_operator", &RNA_Operator); - if (!ptr.data) { - BKE_report(op->reports, RPT_ERROR, "No operator in context"); - return OPERATOR_CANCELLED; - } + if (!ptr.data) { + BKE_report(op->reports, RPT_ERROR, "No operator in context"); + return OPERATOR_CANCELLED; + } - WM_operator_properties_reset((wmOperator *)ptr.data); - return OPERATOR_FINISHED; + WM_operator_properties_reset((wmOperator *)ptr.data); + return OPERATOR_FINISHED; } /* used by operator preset menu. pre-2.65 this was a 'Reset' button */ static void WM_OT_operator_defaults(wmOperatorType *ot) { - ot->name = "Restore Defaults"; - ot->idname = "WM_OT_operator_defaults"; - ot->description = "Set the active operator to its default values"; + ot->name = "Restore Defaults"; + ot->idname = "WM_OT_operator_defaults"; + ot->description = "Set the active operator to its default values"; - ot->exec = wm_operator_defaults_exec; + ot->exec = wm_operator_defaults_exec; - ot->flag = OPTYPE_INTERNAL; + ot->flag = OPTYPE_INTERNAL; } /* ***************** Splash Screen ************************* */ static void wm_block_splash_close(bContext *C, void *arg_block, void *UNUSED(arg)) { - wmWindow *win = CTX_wm_window(C); - UI_popup_block_close(C, win, arg_block); + wmWindow *win = CTX_wm_window(C); + UI_popup_block_close(C, win, arg_block); } static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *arg_unused); static void wm_block_splash_refreshmenu(bContext *C, void *UNUSED(arg_block), void *UNUSED(arg)) { - ARegion *ar_menu = CTX_wm_menu(C); - ED_region_tag_refresh_ui(ar_menu); + ARegion *ar_menu = CTX_wm_menu(C); + ED_region_tag_refresh_ui(ar_menu); } static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(arg)) { - uiBlock *block; - uiBut *but; - uiStyle *style = UI_style_get(); + uiBlock *block; + uiBut *but; + uiStyle *style = UI_style_get(); #ifndef WITH_HEADLESS - extern char datatoc_splash_png[]; - extern int datatoc_splash_png_size; + extern char datatoc_splash_png[]; + extern int datatoc_splash_png_size; - extern char datatoc_splash_2x_png[]; - extern int datatoc_splash_2x_png_size; - ImBuf *ibuf; + extern char datatoc_splash_2x_png[]; + extern int datatoc_splash_2x_png_size; + ImBuf *ibuf; #else - ImBuf *ibuf = NULL; + ImBuf *ibuf = NULL; #endif #ifdef WITH_BUILDINFO - int label_delta = 0; - int hash_width, date_width; - char date_buf[128] = "\0"; - char hash_buf[128] = "\0"; - extern unsigned long build_commit_timestamp; - extern char build_hash[], build_commit_date[], build_commit_time[], build_branch[]; - - /* Builds made from tag only shows tag sha */ - BLI_snprintf(hash_buf, sizeof(hash_buf), "Hash: %s", build_hash); - BLI_snprintf(date_buf, sizeof(date_buf), "Date: %s %s", build_commit_date, build_commit_time); - - BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.pixelsize * U.dpi); - hash_width = (int)BLF_width(style->widgetlabel.uifont_id, hash_buf, sizeof(hash_buf)) + U.widget_unit; - date_width = (int)BLF_width(style->widgetlabel.uifont_id, date_buf, sizeof(date_buf)) + U.widget_unit; -#endif /* WITH_BUILDINFO */ + int label_delta = 0; + int hash_width, date_width; + char date_buf[128] = "\0"; + char hash_buf[128] = "\0"; + extern unsigned long build_commit_timestamp; + extern char build_hash[], build_commit_date[], build_commit_time[], build_branch[]; + + /* Builds made from tag only shows tag sha */ + BLI_snprintf(hash_buf, sizeof(hash_buf), "Hash: %s", build_hash); + BLI_snprintf(date_buf, sizeof(date_buf), "Date: %s %s", build_commit_date, build_commit_time); + + BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.pixelsize * U.dpi); + hash_width = (int)BLF_width(style->widgetlabel.uifont_id, hash_buf, sizeof(hash_buf)) + + U.widget_unit; + date_width = (int)BLF_width(style->widgetlabel.uifont_id, date_buf, sizeof(date_buf)) + + U.widget_unit; +#endif /* WITH_BUILDINFO */ #ifndef WITH_HEADLESS - if (U.dpi_fac > 1.0) { - ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_splash_2x_png, - datatoc_splash_2x_png_size, IB_rect, NULL, "<splash screen>"); - } - else { - ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_splash_png, - datatoc_splash_png_size, IB_rect, NULL, "<splash screen>"); - } - - /* overwrite splash with template image */ - if (U.app_template[0] != '\0') { - ImBuf *ibuf_template = NULL; - char splash_filepath[FILE_MAX]; - char template_directory[FILE_MAX]; - - if (BKE_appdir_app_template_id_search( - U.app_template, - template_directory, sizeof(template_directory))) - { - BLI_join_dirfile( - splash_filepath, sizeof(splash_filepath), template_directory, - (U.pixelsize == 2) ? "splash_2x.png" : "splash.png"); - ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL); - if (ibuf_template) { - const int x_expect = ibuf->x; - const int y_expect = 250 * (int)U.dpi_fac; - /* don't cover the header text */ - if (ibuf_template->x == x_expect && ibuf_template->y == y_expect) { - memcpy(ibuf->rect, ibuf_template->rect, ibuf_template->x * ibuf_template->y * sizeof(char[4])); - } - else { - CLOG_ERROR(WM_LOG_OPERATORS, - "Splash expected %dx%d found %dx%d, ignoring: %s\n", - x_expect, y_expect, ibuf_template->x, ibuf_template->y, splash_filepath); - } - IMB_freeImBuf(ibuf_template); - } - } - } + if (U.dpi_fac > 1.0) { + ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_splash_2x_png, + datatoc_splash_2x_png_size, + IB_rect, + NULL, + "<splash screen>"); + } + else { + ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_splash_png, + datatoc_splash_png_size, + IB_rect, + NULL, + "<splash screen>"); + } + + /* overwrite splash with template image */ + if (U.app_template[0] != '\0') { + ImBuf *ibuf_template = NULL; + char splash_filepath[FILE_MAX]; + char template_directory[FILE_MAX]; + + if (BKE_appdir_app_template_id_search( + U.app_template, template_directory, sizeof(template_directory))) { + BLI_join_dirfile(splash_filepath, + sizeof(splash_filepath), + template_directory, + (U.pixelsize == 2) ? "splash_2x.png" : "splash.png"); + ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL); + if (ibuf_template) { + const int x_expect = ibuf->x; + const int y_expect = 250 * (int)U.dpi_fac; + /* don't cover the header text */ + if (ibuf_template->x == x_expect && ibuf_template->y == y_expect) { + memcpy(ibuf->rect, + ibuf_template->rect, + ibuf_template->x * ibuf_template->y * sizeof(char[4])); + } + else { + CLOG_ERROR(WM_LOG_OPERATORS, + "Splash expected %dx%d found %dx%d, ignoring: %s\n", + x_expect, + y_expect, + ibuf_template->x, + ibuf_template->y, + splash_filepath); + } + IMB_freeImBuf(ibuf_template); + } + } + } #endif - block = UI_block_begin(C, ar, "splash", UI_EMBOSS); - - /* note on UI_BLOCK_NO_WIN_CLIP, the window size is not always synchronized - * with the OS when the splash shows, window clipping in this case gives - * ugly results and clipping the splash isn't useful anyway, just disable it [#32938] */ - UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP); - UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); - - but = uiDefBut(block, UI_BTYPE_IMAGE, 0, "", 0, 0.5f * U.widget_unit, U.dpi_fac * 501, U.dpi_fac * 250, ibuf, 0.0, 0.0, 0, 0, ""); /* button owns the imbuf now */ - UI_but_func_set(but, wm_block_splash_close, block, NULL); - UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL); - - /* label for 'a' bugfix releases, or 'Release Candidate 1'... - * avoids recreating splash for version updates */ - const char *version_suffix = NULL; - - if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) { - version_suffix = " Alpha"; - } - else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) { - version_suffix = " Beta"; - } - else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) { - version_suffix = " Release Candidate"; - } - else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) { - version_suffix = STRINGIFY(BLENDER_VERSION_CHAR); - } - - char *version = BLI_sprintfN("Version %d.%d%s", BLENDER_VERSION / 100, BLENDER_VERSION % 100, version_suffix); - - if (version != NULL && version[0]) { - /* placed after the version number in the image, - * placing y is tricky to match baseline */ - /* hack to have text draw 'text_sel' */ - UI_block_emboss_set(block, UI_EMBOSS_NONE); - int x = 202 * U.dpi_fac; - int y = 130 * U.dpi_fac; - int w = 240 * U.dpi_fac; - - - but = uiDefBut(block, UI_BTYPE_LABEL, 0, version, x, y, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); - /* XXX, set internal flag - UI_SELECT */ - UI_but_flag_enable(but, 1); - UI_block_emboss_set(block, UI_EMBOSS); - } - - MEM_freeN(version); + block = UI_block_begin(C, ar, "splash", UI_EMBOSS); + + /* note on UI_BLOCK_NO_WIN_CLIP, the window size is not always synchronized + * with the OS when the splash shows, window clipping in this case gives + * ugly results and clipping the splash isn't useful anyway, just disable it [#32938] */ + UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); + + but = uiDefBut(block, + UI_BTYPE_IMAGE, + 0, + "", + 0, + 0.5f * U.widget_unit, + U.dpi_fac * 501, + U.dpi_fac * 250, + ibuf, + 0.0, + 0.0, + 0, + 0, + ""); /* button owns the imbuf now */ + UI_but_func_set(but, wm_block_splash_close, block, NULL); + UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL); + + /* label for 'a' bugfix releases, or 'Release Candidate 1'... + * avoids recreating splash for version updates */ + const char *version_suffix = NULL; + + if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) { + version_suffix = " Alpha"; + } + else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) { + version_suffix = " Beta"; + } + else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) { + version_suffix = " Release Candidate"; + } + else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) { + version_suffix = STRINGIFY(BLENDER_VERSION_CHAR); + } + + char *version = BLI_sprintfN( + "Version %d.%d%s", BLENDER_VERSION / 100, BLENDER_VERSION % 100, version_suffix); + + if (version != NULL && version[0]) { + /* placed after the version number in the image, + * placing y is tricky to match baseline */ + /* hack to have text draw 'text_sel' */ + UI_block_emboss_set(block, UI_EMBOSS_NONE); + int x = 202 * U.dpi_fac; + int y = 130 * U.dpi_fac; + int w = 240 * U.dpi_fac; + + but = uiDefBut(block, UI_BTYPE_LABEL, 0, version, x, y, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + /* XXX, set internal flag - UI_SELECT */ + UI_but_flag_enable(but, 1); + UI_block_emboss_set(block, UI_EMBOSS); + } + + MEM_freeN(version); #ifdef WITH_BUILDINFO - if (build_commit_timestamp != 0) { - but = uiDefBut( - block, UI_BTYPE_LABEL, 0, date_buf, - U.dpi_fac * 502 - date_width, U.dpi_fac * 237, - date_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); - /* XXX, set internal flag - UI_SELECT */ - UI_but_flag_enable(but, 0); - label_delta = 12; - } - but = uiDefBut( - block, UI_BTYPE_LABEL, 0, hash_buf, - U.dpi_fac * 502 - hash_width, U.dpi_fac * (237 - label_delta), - hash_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); - /* XXX, set internal flag - UI_SELECT */ - UI_but_flag_enable(but, 0); - - if (!STREQ(build_branch, "master")) { - char branch_buf[128] = "\0"; - int branch_width; - BLI_snprintf(branch_buf, sizeof(branch_buf), "Branch: %s", build_branch); - branch_width = (int)BLF_width(style->widgetlabel.uifont_id, branch_buf, sizeof(branch_buf)) + U.widget_unit; - but = uiDefBut( - block, UI_BTYPE_LABEL, 0, branch_buf, - U.dpi_fac * 502 - branch_width, U.dpi_fac * (225 - label_delta), - branch_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); - /* XXX, set internal flag - UI_SELECT */ - UI_but_flag_enable(but, 0); - } -#endif /* WITH_BUILDINFO */ - - uiLayout *layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, U.dpi_fac * 40, 0, - U.dpi_fac * 450, U.dpi_fac * 110, 0, style); - - MenuType *mt = WM_menutype_find("WM_MT_splash", true); - if (mt) { - UI_menutype_draw(C, mt, layout); - } - - UI_block_bounds_set_centered(block, 0); - - return block; + if (build_commit_timestamp != 0) { + but = uiDefBut(block, + UI_BTYPE_LABEL, + 0, + date_buf, + U.dpi_fac * 502 - date_width, + U.dpi_fac * 237, + date_width, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + NULL); + /* XXX, set internal flag - UI_SELECT */ + UI_but_flag_enable(but, 0); + label_delta = 12; + } + but = uiDefBut(block, + UI_BTYPE_LABEL, + 0, + hash_buf, + U.dpi_fac * 502 - hash_width, + U.dpi_fac * (237 - label_delta), + hash_width, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + NULL); + /* XXX, set internal flag - UI_SELECT */ + UI_but_flag_enable(but, 0); + + if (!STREQ(build_branch, "master")) { + char branch_buf[128] = "\0"; + int branch_width; + BLI_snprintf(branch_buf, sizeof(branch_buf), "Branch: %s", build_branch); + branch_width = (int)BLF_width(style->widgetlabel.uifont_id, branch_buf, sizeof(branch_buf)) + + U.widget_unit; + but = uiDefBut(block, + UI_BTYPE_LABEL, + 0, + branch_buf, + U.dpi_fac * 502 - branch_width, + U.dpi_fac * (225 - label_delta), + branch_width, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + NULL); + /* XXX, set internal flag - UI_SELECT */ + UI_but_flag_enable(but, 0); + } +#endif /* WITH_BUILDINFO */ + + uiLayout *layout = UI_block_layout(block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + U.dpi_fac * 40, + 0, + U.dpi_fac * 450, + U.dpi_fac * 110, + 0, + style); + + MenuType *mt = WM_menutype_find("WM_MT_splash", true); + if (mt) { + UI_menutype_draw(C, mt, layout); + } + + UI_block_bounds_set_centered(block, 0); + + return block; } static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { - UI_popup_block_invoke(C, wm_block_create_splash, NULL); + UI_popup_block_invoke(C, wm_block_create_splash, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void WM_OT_splash(wmOperatorType *ot) { - ot->name = "Splash Screen"; - ot->idname = "WM_OT_splash"; - ot->description = "Open the splash screen with release info"; + ot->name = "Splash Screen"; + ot->idname = "WM_OT_splash"; + ot->description = "Open the splash screen with release info"; - ot->invoke = wm_splash_invoke; - ot->poll = WM_operator_winactive; + ot->invoke = wm_splash_invoke; + ot->poll = WM_operator_winactive; } - /* ***************** Search menu ************************* */ struct SearchPopupInit_Data { - int size[2]; + int size[2]; }; static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *userdata) { - const struct SearchPopupInit_Data *init_data = userdata; - static char search[256] = ""; - uiBlock *block; - uiBut *but; - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); - UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); - - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, init_data->size[0], UI_UNIT_Y, 0, 0, ""); - UI_but_func_operator_search(but); - UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); - - /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - init_data->size[1], - init_data->size[0], init_data->size[1], NULL, 0, 0, 0, 0, NULL); - - /* Move it downwards, mouse over button. */ - UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y}); - - return block; + const struct SearchPopupInit_Data *init_data = userdata; + static char search[256] = ""; + uiBlock *block; + uiBut *but; + + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); + UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); + + but = uiDefSearchBut(block, + search, + 0, + ICON_VIEWZOOM, + sizeof(search), + 10, + 10, + init_data->size[0], + UI_UNIT_Y, + 0, + 0, + ""); + UI_but_func_operator_search(but); + UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); + + /* fake button, it holds space for search items */ + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + "", + 10, + 10 - init_data->size[1], + init_data->size[0], + init_data->size[1], + NULL, + 0, + 0, + 0, + 0, + NULL); + + /* Move it downwards, mouse over button. */ + UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y}); + + return block; } static int wm_search_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int wm_search_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { - /* Exception for launching via spacebar */ - if (event->type == SPACEKEY) { - bool ok = true; - ScrArea *sa = CTX_wm_area(C); - if (sa) { - if (sa->spacetype == SPACE_CONSOLE) { - /* So we can use the shortcut in the console. */ - ok = false; - } - else if (sa->spacetype == SPACE_TEXT) { - /* So we can use the spacebar in the text editor. */ - ok = false; - } - } - else { - Object *editob = CTX_data_edit_object(C); - if (editob && editob->type == OB_FONT) { - /* So we can use the spacebar for entering text. */ - ok = false; - } - } - if (!ok) { - return OPERATOR_PASS_THROUGH; - } - } - - - static struct SearchPopupInit_Data data; - data.size[0] = UI_searchbox_size_x() * 2; - data.size[1] = UI_searchbox_size_y(); - - UI_popup_block_invoke(C, wm_block_search_menu, &data); - - return OPERATOR_INTERFACE; + /* Exception for launching via spacebar */ + if (event->type == SPACEKEY) { + bool ok = true; + ScrArea *sa = CTX_wm_area(C); + if (sa) { + if (sa->spacetype == SPACE_CONSOLE) { + /* So we can use the shortcut in the console. */ + ok = false; + } + else if (sa->spacetype == SPACE_TEXT) { + /* So we can use the spacebar in the text editor. */ + ok = false; + } + } + else { + Object *editob = CTX_data_edit_object(C); + if (editob && editob->type == OB_FONT) { + /* So we can use the spacebar for entering text. */ + ok = false; + } + } + if (!ok) { + return OPERATOR_PASS_THROUGH; + } + } + + static struct SearchPopupInit_Data data; + data.size[0] = UI_searchbox_size_x() * 2; + data.size[1] = UI_searchbox_size_y(); + + UI_popup_block_invoke(C, wm_block_search_menu, &data); + + return OPERATOR_INTERFACE; } static void WM_OT_search_menu(wmOperatorType *ot) { - ot->name = "Search Menu"; - ot->idname = "WM_OT_search_menu"; - ot->description = "Pop-up a search menu over all available operators in current context"; + ot->name = "Search Menu"; + ot->idname = "WM_OT_search_menu"; + ot->description = "Pop-up a search menu over all available operators in current context"; - ot->invoke = wm_search_menu_invoke; - ot->exec = wm_search_menu_exec; - ot->poll = WM_operator_winactive; + ot->invoke = wm_search_menu_invoke; + ot->exec = wm_search_menu_exec; + ot->poll = WM_operator_winactive; } static int wm_call_menu_exec(bContext *C, wmOperator *op) { - char idname[BKE_ST_MAXNAME]; - RNA_string_get(op->ptr, "name", idname); + char idname[BKE_ST_MAXNAME]; + RNA_string_get(op->ptr, "name", idname); - return UI_popup_menu_invoke(C, idname, op->reports); + return UI_popup_menu_invoke(C, idname, op->reports); } static void WM_OT_call_menu(wmOperatorType *ot) { - ot->name = "Call Menu"; - ot->idname = "WM_OT_call_menu"; - ot->description = "Call (draw) a pre-defined menu"; + ot->name = "Call Menu"; + ot->idname = "WM_OT_call_menu"; + ot->description = "Call (draw) a pre-defined menu"; - ot->exec = wm_call_menu_exec; - ot->poll = WM_operator_winactive; + ot->exec = wm_call_menu_exec; + ot->poll = WM_operator_winactive; - ot->flag = OPTYPE_INTERNAL; + ot->flag = OPTYPE_INTERNAL; - RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the menu"); + RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the menu"); } static int wm_call_pie_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - char idname[BKE_ST_MAXNAME]; - RNA_string_get(op->ptr, "name", idname); + char idname[BKE_ST_MAXNAME]; + RNA_string_get(op->ptr, "name", idname); - return UI_pie_menu_invoke(C, idname, event); + return UI_pie_menu_invoke(C, idname, event); } static int wm_call_pie_menu_exec(bContext *C, wmOperator *op) { - char idname[BKE_ST_MAXNAME]; - RNA_string_get(op->ptr, "name", idname); + char idname[BKE_ST_MAXNAME]; + RNA_string_get(op->ptr, "name", idname); - return UI_pie_menu_invoke(C, idname, CTX_wm_window(C)->eventstate); + return UI_pie_menu_invoke(C, idname, CTX_wm_window(C)->eventstate); } static void WM_OT_call_menu_pie(wmOperatorType *ot) { - ot->name = "Call Pie Menu"; - ot->idname = "WM_OT_call_menu_pie"; - ot->description = "Call (draw) a pre-defined pie menu"; + ot->name = "Call Pie Menu"; + ot->idname = "WM_OT_call_menu_pie"; + ot->description = "Call (draw) a pre-defined pie menu"; - ot->invoke = wm_call_pie_menu_invoke; - ot->exec = wm_call_pie_menu_exec; - ot->poll = WM_operator_winactive; + ot->invoke = wm_call_pie_menu_invoke; + ot->exec = wm_call_pie_menu_exec; + ot->poll = WM_operator_winactive; - ot->flag = OPTYPE_INTERNAL; + ot->flag = OPTYPE_INTERNAL; - RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the pie menu"); + RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the pie menu"); } static int wm_call_panel_exec(bContext *C, wmOperator *op) { - char idname[BKE_ST_MAXNAME]; - RNA_string_get(op->ptr, "name", idname); - const bool keep_open = RNA_boolean_get(op->ptr, "keep_open"); + char idname[BKE_ST_MAXNAME]; + RNA_string_get(op->ptr, "name", idname); + const bool keep_open = RNA_boolean_get(op->ptr, "keep_open"); - return UI_popover_panel_invoke(C, idname, keep_open, op->reports); + return UI_popover_panel_invoke(C, idname, keep_open, op->reports); } static void WM_OT_call_panel(wmOperatorType *ot) { - ot->name = "Call Panel"; - ot->idname = "WM_OT_call_panel"; - ot->description = "Call (draw) a pre-defined panel"; + ot->name = "Call Panel"; + ot->idname = "WM_OT_call_panel"; + ot->description = "Call (draw) a pre-defined panel"; - ot->exec = wm_call_panel_exec; - ot->poll = WM_operator_winactive; + ot->exec = wm_call_panel_exec; + ot->poll = WM_operator_winactive; - ot->flag = OPTYPE_INTERNAL; + ot->flag = OPTYPE_INTERNAL; - PropertyRNA *prop; + PropertyRNA *prop; - prop = RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the menu"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "keep_open", true, "Keep Open", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the menu"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "keep_open", true, "Keep Open", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ************ window / screen operator definitions ************** */ @@ -1769,85 +1903,87 @@ static void WM_OT_call_panel(wmOperatorType *ot) * while it crashes on full screen */ static bool wm_operator_winactive_normal(bContext *C) { - wmWindow *win = CTX_wm_window(C); - bScreen *screen; + wmWindow *win = CTX_wm_window(C); + bScreen *screen; - if (win == NULL) { - return 0; - } - if (!((screen = WM_window_get_active_screen(win)) && (screen->state == SCREENNORMAL))) { - return 0; - } + if (win == NULL) { + return 0; + } + if (!((screen = WM_window_get_active_screen(win)) && (screen->state == SCREENNORMAL))) { + return 0; + } - return 1; + return 1; } /* included for script-access */ static void WM_OT_window_close(wmOperatorType *ot) { - ot->name = "Close Window"; - ot->idname = "WM_OT_window_close"; - ot->description = "Close the current window"; + ot->name = "Close Window"; + ot->idname = "WM_OT_window_close"; + ot->description = "Close the current window"; - ot->exec = wm_window_close_exec; - ot->poll = WM_operator_winactive; + ot->exec = wm_window_close_exec; + ot->poll = WM_operator_winactive; } static void WM_OT_window_new(wmOperatorType *ot) { - ot->name = "New Window"; - ot->idname = "WM_OT_window_new"; - ot->description = "Create a new window"; + ot->name = "New Window"; + ot->idname = "WM_OT_window_new"; + ot->description = "Create a new window"; - ot->exec = wm_window_new_exec; - ot->poll = wm_operator_winactive_normal; + ot->exec = wm_window_new_exec; + ot->poll = wm_operator_winactive_normal; } static void WM_OT_window_new_main(wmOperatorType *ot) { - ot->name = "New Main Window"; - ot->idname = "WM_OT_window_new_main"; - ot->description = "Create a new main window with its own workspace and scene selection"; + ot->name = "New Main Window"; + ot->idname = "WM_OT_window_new_main"; + ot->description = "Create a new main window with its own workspace and scene selection"; - ot->exec = wm_window_new_main_exec; - ot->poll = wm_operator_winactive_normal; + ot->exec = wm_window_new_main_exec; + ot->poll = wm_operator_winactive_normal; } static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot) { - ot->name = "Toggle Window Fullscreen"; - ot->idname = "WM_OT_window_fullscreen_toggle"; - ot->description = "Toggle the current window fullscreen"; + ot->name = "Toggle Window Fullscreen"; + ot->idname = "WM_OT_window_fullscreen_toggle"; + ot->description = "Toggle the current window fullscreen"; - ot->exec = wm_window_fullscreen_toggle_exec; - ot->poll = WM_operator_winactive; + ot->exec = wm_window_fullscreen_toggle_exec; + ot->poll = WM_operator_winactive; } static int wm_exit_blender_exec(bContext *C, wmOperator *UNUSED(op)) { - wm_exit_schedule_delayed(C); - return OPERATOR_FINISHED; + wm_exit_schedule_delayed(C); + return OPERATOR_FINISHED; } -static int wm_exit_blender_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) +static int wm_exit_blender_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *UNUSED(event)) { - if (U.uiflag & USER_SAVE_PROMPT) { - wm_quit_with_optional_confirmation_prompt(C, CTX_wm_window(C)); - } - else { - wm_exit_schedule_delayed(C); - } - return OPERATOR_FINISHED; + if (U.uiflag & USER_SAVE_PROMPT) { + wm_quit_with_optional_confirmation_prompt(C, CTX_wm_window(C)); + } + else { + wm_exit_schedule_delayed(C); + } + return OPERATOR_FINISHED; } static void WM_OT_quit_blender(wmOperatorType *ot) { - ot->name = "Quit Blender"; - ot->idname = "WM_OT_quit_blender"; - ot->description = "Quit Blender"; + ot->name = "Quit Blender"; + ot->idname = "WM_OT_quit_blender"; + ot->description = "Quit Blender"; - ot->invoke = wm_exit_blender_invoke; - ot->exec = wm_exit_blender_exec; + ot->invoke = wm_exit_blender_invoke; + ot->exec = wm_exit_blender_exec; } /* *********************** */ @@ -1856,19 +1992,19 @@ static void WM_OT_quit_blender(wmOperatorType *ot) static int wm_console_toggle_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { - GHOST_toggleConsole(2); - return OPERATOR_FINISHED; + GHOST_toggleConsole(2); + return OPERATOR_FINISHED; } static void WM_OT_console_toggle(wmOperatorType *ot) { - /* XXX Have to mark these for xgettext, as under linux they do not exists... */ - ot->name = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Toggle System Console"); - ot->idname = "WM_OT_console_toggle"; - ot->description = N_("Toggle System Console"); + /* XXX Have to mark these for xgettext, as under linux they do not exists... */ + ot->name = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Toggle System Console"); + ot->idname = "WM_OT_console_toggle"; + ot->description = N_("Toggle System Console"); - ot->exec = wm_console_toggle_exec; - ot->poll = WM_operator_winactive; + ot->exec = wm_console_toggle_exec; + ot->poll = WM_operator_winactive; } #endif @@ -1880,379 +2016,388 @@ static void WM_OT_console_toggle(wmOperatorType *ot) * - draw(bContext): drawing callback for paint cursor */ -wmPaintCursor *WM_paint_cursor_activate( - wmWindowManager *wm, - short space_type, short region_type, - bool (*poll)(bContext *C), - wmPaintCursorDraw draw, void *customdata) +wmPaintCursor *WM_paint_cursor_activate(wmWindowManager *wm, + short space_type, + short region_type, + bool (*poll)(bContext *C), + wmPaintCursorDraw draw, + void *customdata) { - wmPaintCursor *pc = MEM_callocN(sizeof(wmPaintCursor), "paint cursor"); + wmPaintCursor *pc = MEM_callocN(sizeof(wmPaintCursor), "paint cursor"); - BLI_addtail(&wm->paintcursors, pc); + BLI_addtail(&wm->paintcursors, pc); - pc->customdata = customdata; - pc->poll = poll; - pc->draw = draw; + pc->customdata = customdata; + pc->poll = poll; + pc->draw = draw; - pc->space_type = space_type; - pc->region_type = region_type; + pc->space_type = space_type; + pc->region_type = region_type; - return pc; + return pc; } bool WM_paint_cursor_end(wmWindowManager *wm, wmPaintCursor *handle) { - wmPaintCursor *pc; + wmPaintCursor *pc; - for (pc = wm->paintcursors.first; pc; pc = pc->next) { - if (pc == (wmPaintCursor *)handle) { - BLI_remlink(&wm->paintcursors, pc); - MEM_freeN(pc); - return true; - } - } - return false; + for (pc = wm->paintcursors.first; pc; pc = pc->next) { + if (pc == (wmPaintCursor *)handle) { + BLI_remlink(&wm->paintcursors, pc); + MEM_freeN(pc); + return true; + } + } + return false; } /* *********************** radial control ****************** */ #define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * UI_DPI_FAC) #define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * UI_DPI_FAC) -#define WM_RADIAL_CONTROL_DISPLAY_WIDTH (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) +#define WM_RADIAL_CONTROL_DISPLAY_WIDTH \ + (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) #define WM_RADIAL_MAX_STR 10 typedef struct { - PropertyType type; - PropertySubType subtype; - PointerRNA ptr, col_ptr, fill_col_ptr, rot_ptr, zoom_ptr, image_id_ptr; - PointerRNA fill_col_override_ptr, fill_col_override_test_ptr; - PropertyRNA *prop, *col_prop, *fill_col_prop, *rot_prop, *zoom_prop; - PropertyRNA *fill_col_override_prop, *fill_col_override_test_prop; - StructRNA *image_id_srna; - float initial_value, current_value, min_value, max_value; - int initial_mouse[2]; - int slow_mouse[2]; - bool slow_mode; - Dial *dial; - unsigned int gltex; - ListBase orig_paintcursors; - bool use_secondary_tex; - void *cursor; - NumInput num_input; + PropertyType type; + PropertySubType subtype; + PointerRNA ptr, col_ptr, fill_col_ptr, rot_ptr, zoom_ptr, image_id_ptr; + PointerRNA fill_col_override_ptr, fill_col_override_test_ptr; + PropertyRNA *prop, *col_prop, *fill_col_prop, *rot_prop, *zoom_prop; + PropertyRNA *fill_col_override_prop, *fill_col_override_test_prop; + StructRNA *image_id_srna; + float initial_value, current_value, min_value, max_value; + int initial_mouse[2]; + int slow_mouse[2]; + bool slow_mode; + Dial *dial; + unsigned int gltex; + ListBase orig_paintcursors; + bool use_secondary_tex; + void *cursor; + NumInput num_input; } RadialControl; static void radial_control_update_header(wmOperator *op, bContext *C) { - RadialControl *rc = op->customdata; - char msg[UI_MAX_DRAW_STR]; - ScrArea *sa = CTX_wm_area(C); - Scene *scene = CTX_data_scene(C); - - if (hasNumInput(&rc->num_input)) { - char num_str[NUM_STR_REP_LEN]; - outputNumInput(&rc->num_input, num_str, &scene->unit); - BLI_snprintf(msg, sizeof(msg), "%s: %s", RNA_property_ui_name(rc->prop), num_str); - } - else { - const char *ui_name = RNA_property_ui_name(rc->prop); - switch (rc->subtype) { - case PROP_NONE: - case PROP_DISTANCE: - BLI_snprintf(msg, sizeof(msg), "%s: %0.4f", ui_name, rc->current_value); - break; - case PROP_PIXEL: - BLI_snprintf(msg, sizeof(msg), "%s: %d", ui_name, (int)rc->current_value); /* XXX: round to nearest? */ - break; - case PROP_PERCENTAGE: - BLI_snprintf(msg, sizeof(msg), "%s: %3.1f%%", ui_name, rc->current_value); - break; - case PROP_FACTOR: - BLI_snprintf(msg, sizeof(msg), "%s: %1.3f", ui_name, rc->current_value); - break; - case PROP_ANGLE: - BLI_snprintf(msg, sizeof(msg), "%s: %3.2f", ui_name, RAD2DEGF(rc->current_value)); - break; - default: - BLI_snprintf(msg, sizeof(msg), "%s", ui_name); /* XXX: No value? */ - break; - } - } - - ED_area_status_text(sa, msg); + RadialControl *rc = op->customdata; + char msg[UI_MAX_DRAW_STR]; + ScrArea *sa = CTX_wm_area(C); + Scene *scene = CTX_data_scene(C); + + if (hasNumInput(&rc->num_input)) { + char num_str[NUM_STR_REP_LEN]; + outputNumInput(&rc->num_input, num_str, &scene->unit); + BLI_snprintf(msg, sizeof(msg), "%s: %s", RNA_property_ui_name(rc->prop), num_str); + } + else { + const char *ui_name = RNA_property_ui_name(rc->prop); + switch (rc->subtype) { + case PROP_NONE: + case PROP_DISTANCE: + BLI_snprintf(msg, sizeof(msg), "%s: %0.4f", ui_name, rc->current_value); + break; + case PROP_PIXEL: + BLI_snprintf(msg, + sizeof(msg), + "%s: %d", + ui_name, + (int)rc->current_value); /* XXX: round to nearest? */ + break; + case PROP_PERCENTAGE: + BLI_snprintf(msg, sizeof(msg), "%s: %3.1f%%", ui_name, rc->current_value); + break; + case PROP_FACTOR: + BLI_snprintf(msg, sizeof(msg), "%s: %1.3f", ui_name, rc->current_value); + break; + case PROP_ANGLE: + BLI_snprintf(msg, sizeof(msg), "%s: %3.2f", ui_name, RAD2DEGF(rc->current_value)); + break; + default: + BLI_snprintf(msg, sizeof(msg), "%s", ui_name); /* XXX: No value? */ + break; + } + } + + ED_area_status_text(sa, msg); } static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event) { - float d[2] = {0, 0}; - float zoom[2] = {1, 1}; - - rc->initial_mouse[0] = event->x; - rc->initial_mouse[1] = event->y; - - switch (rc->subtype) { - case PROP_NONE: - case PROP_DISTANCE: - case PROP_PIXEL: - d[0] = rc->initial_value; - break; - case PROP_PERCENTAGE: - d[0] = (rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; - break; - case PROP_FACTOR: - d[0] = (1 - rc->initial_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; - break; - case PROP_ANGLE: - d[0] = WM_RADIAL_CONTROL_DISPLAY_SIZE * cosf(rc->initial_value); - d[1] = WM_RADIAL_CONTROL_DISPLAY_SIZE * sinf(rc->initial_value); - break; - default: - return; - } - - if (rc->zoom_prop) { - RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); - d[0] *= zoom[0]; - d[1] *= zoom[1]; - } - - rc->initial_mouse[0] -= d[0]; - rc->initial_mouse[1] -= d[1]; + float d[2] = {0, 0}; + float zoom[2] = {1, 1}; + + rc->initial_mouse[0] = event->x; + rc->initial_mouse[1] = event->y; + + switch (rc->subtype) { + case PROP_NONE: + case PROP_DISTANCE: + case PROP_PIXEL: + d[0] = rc->initial_value; + break; + case PROP_PERCENTAGE: + d[0] = (rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + break; + case PROP_FACTOR: + d[0] = (1 - rc->initial_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + break; + case PROP_ANGLE: + d[0] = WM_RADIAL_CONTROL_DISPLAY_SIZE * cosf(rc->initial_value); + d[1] = WM_RADIAL_CONTROL_DISPLAY_SIZE * sinf(rc->initial_value); + break; + default: + return; + } + + if (rc->zoom_prop) { + RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); + d[0] *= zoom[0]; + d[1] *= zoom[1]; + } + + rc->initial_mouse[0] -= d[0]; + rc->initial_mouse[1] -= d[1]; } static void radial_control_set_tex(RadialControl *rc) { - ImBuf *ibuf; - - switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) { - case ID_BR: - if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data, rc->use_secondary_tex))) { - glGenTextures(1, &rc->gltex); - glBindTexture(GL_TEXTURE_2D, rc->gltex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, ibuf->x, ibuf->y, 0, - GL_RED, GL_FLOAT, ibuf->rect_float); - glBindTexture(GL_TEXTURE_2D, 0); - MEM_freeN(ibuf->rect_float); - MEM_freeN(ibuf); - } - break; - default: - break; - } + ImBuf *ibuf; + + switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) { + case ID_BR: + if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data, + rc->use_secondary_tex))) { + glGenTextures(1, &rc->gltex); + glBindTexture(GL_TEXTURE_2D, rc->gltex); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_R8, ibuf->x, ibuf->y, 0, GL_RED, GL_FLOAT, ibuf->rect_float); + glBindTexture(GL_TEXTURE_2D, 0); + 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; + float col[3] = {0, 0, 0}; + float rot; - /* set fill color */ - if (rc->fill_col_prop) { - PointerRNA *fill_ptr; - PropertyRNA *fill_prop; + /* set fill color */ + if (rc->fill_col_prop) { + PointerRNA *fill_ptr; + PropertyRNA *fill_prop; - if (rc->fill_col_override_prop && - RNA_property_boolean_get(&rc->fill_col_override_test_ptr, rc->fill_col_override_test_prop)) - { - fill_ptr = &rc->fill_col_override_ptr; - fill_prop = rc->fill_col_override_prop; - } - else { - fill_ptr = &rc->fill_col_ptr; - fill_prop = rc->fill_col_prop; - } + if (rc->fill_col_override_prop && RNA_property_boolean_get(&rc->fill_col_override_test_ptr, + rc->fill_col_override_test_prop)) { + fill_ptr = &rc->fill_col_override_ptr; + fill_prop = rc->fill_col_override_prop; + } + else { + fill_ptr = &rc->fill_col_ptr; + fill_prop = rc->fill_col_prop; + } - RNA_property_float_get_array(fill_ptr, fill_prop, col); - } + RNA_property_float_get_array(fill_ptr, fill_prop, col); + } - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - if (rc->gltex) { + if (rc->gltex) { - uint texCoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint texCoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, rc->gltex); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rc->gltex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - GLint swizzleMask[] = {GL_ZERO, GL_ZERO, GL_ZERO, GL_RED}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + GLint swizzleMask[] = {GL_ZERO, GL_ZERO, GL_ZERO, GL_RED}; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - /* set up rotation if available */ - if (rc->rot_prop) { - rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop); - GPU_matrix_push(); - GPU_matrix_rotate_2d(RAD2DEGF(rot)); - } + /* set up rotation if available */ + if (rc->rot_prop) { + rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop); + GPU_matrix_push(); + GPU_matrix_rotate_2d(RAD2DEGF(rot)); + } - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR); - immUniformColor3fvAlpha(col, alpha); - immUniform1i("image", 0); + immUniformColor3fvAlpha(col, alpha); + immUniform1i("image", 0); - /* draw textured quad */ - immBegin(GPU_PRIM_TRI_FAN, 4); + /* draw textured quad */ + immBegin(GPU_PRIM_TRI_FAN, 4); - immAttr2f(texCoord, 0, 0); - immVertex2f(pos, -radius, -radius); + immAttr2f(texCoord, 0, 0); + immVertex2f(pos, -radius, -radius); - immAttr2f(texCoord, 1, 0); - immVertex2f(pos, radius, -radius); + immAttr2f(texCoord, 1, 0); + immVertex2f(pos, radius, -radius); - immAttr2f(texCoord, 1, 1); - immVertex2f(pos, radius, radius); + immAttr2f(texCoord, 1, 1); + immVertex2f(pos, radius, radius); - immAttr2f(texCoord, 0, 1); - immVertex2f(pos, -radius, radius); + immAttr2f(texCoord, 0, 1); + immVertex2f(pos, -radius, radius); - immEnd(); + immEnd(); - /* undo rotation */ - if (rc->rot_prop) { - GPU_matrix_pop(); - } - } - else { - /* flat color if no texture available */ - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor3fvAlpha(col, alpha); - imm_draw_circle_fill_2d(pos, 0.0f, 0.0f, radius, 40); - } + /* undo rotation */ + if (rc->rot_prop) { + GPU_matrix_pop(); + } + } + else { + /* flat color if no texture available */ + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3fvAlpha(col, alpha); + imm_draw_circle_fill_2d(pos, 0.0f, 0.0f, radius, 40); + } - immUnbindProgram(); + immUnbindProgram(); } static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void *customdata) { - RadialControl *rc = customdata; - uiStyle *style = UI_style_get(); - const uiFontStyle *fstyle = &style->widget; - const int fontid = fstyle->uifont_id; - short fstyle_points = fstyle->points; - char str[WM_RADIAL_MAX_STR]; - short strdrawlen = 0; - float strwidth, strheight; - float r1 = 0.0f, r2 = 0.0f, rmin = 0.0, tex_radius, alpha; - float zoom[2], col[3] = {1, 1, 1}; - - switch (rc->subtype) { - case PROP_NONE: - case PROP_DISTANCE: - case PROP_PIXEL: - r1 = rc->current_value; - r2 = rc->initial_value; - tex_radius = r1; - alpha = 0.75; - break; - case PROP_PERCENTAGE: - r1 = rc->current_value / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; - r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; - rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; - BLI_snprintf(str, WM_RADIAL_MAX_STR, "%3.1f%%", rc->current_value); - strdrawlen = BLI_strlen_utf8(str); - tex_radius = r1; - alpha = 0.75; - break; - case PROP_FACTOR: - r1 = (1 - rc->current_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; - r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; - rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; - alpha = rc->current_value / 2.0f + 0.5f; - BLI_snprintf(str, WM_RADIAL_MAX_STR, "%1.3f", rc->current_value); - strdrawlen = BLI_strlen_utf8(str); - break; - case PROP_ANGLE: - r1 = r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; - alpha = 0.75; - rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; - BLI_snprintf(str, WM_RADIAL_MAX_STR, "%3.2f", RAD2DEGF(rc->current_value)); - strdrawlen = BLI_strlen_utf8(str); - break; - default: - tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* note, this is a dummy value */ - alpha = 0.75; - break; - } - - /* Keep cursor in the original place */ - x = rc->initial_mouse[0]; - y = rc->initial_mouse[1]; - GPU_matrix_translate_2f((float)x, (float)y); - - GPU_blend(true); - GPU_line_smooth(true); - - /* apply zoom if available */ - if (rc->zoom_prop) { - RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); - GPU_matrix_scale_2fv(zoom); - } - - /* 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); - } - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor3fvAlpha(col, 0.5f); - - if (rc->subtype == PROP_ANGLE) { - GPU_matrix_push(); - - /* draw original angle line */ - GPU_matrix_rotate_3f(RAD2DEGF(rc->initial_value), 0.0f, 0.0f, 1.0f); - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f); - immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f); - immEnd(); - - /* draw new angle line */ - GPU_matrix_rotate_3f(RAD2DEGF(rc->current_value - rc->initial_value), 0.0f, 0.0f, 1.0f); - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f); - immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f); - immEnd(); - - GPU_matrix_pop(); - } - - /* draw circles on top */ - imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r1, 40); - imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r2, 40); - if (rmin > 0.0f) { - imm_draw_circle_wire_2d(pos, 0.0, 0.0f, rmin, 40); - } - immUnbindProgram(); - - BLF_size(fontid, 1.5 * fstyle_points * U.pixelsize, U.dpi); - BLF_enable(fontid, BLF_SHADOW); - BLF_shadow(fontid, 3, (const float[4]){0.0f, 0.0f, 0.0f, 0.5f}); - BLF_shadow_offset(fontid, 1, -1); - - /* draw value */ - BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight); - BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f); - BLF_draw(fontid, str, strdrawlen); - - BLF_disable(fontid, BLF_SHADOW); - - GPU_blend(false); - GPU_line_smooth(false); - + RadialControl *rc = customdata; + uiStyle *style = UI_style_get(); + const uiFontStyle *fstyle = &style->widget; + const int fontid = fstyle->uifont_id; + short fstyle_points = fstyle->points; + char str[WM_RADIAL_MAX_STR]; + short strdrawlen = 0; + float strwidth, strheight; + float r1 = 0.0f, r2 = 0.0f, rmin = 0.0, tex_radius, alpha; + float zoom[2], col[3] = {1, 1, 1}; + + switch (rc->subtype) { + case PROP_NONE: + case PROP_DISTANCE: + case PROP_PIXEL: + r1 = rc->current_value; + r2 = rc->initial_value; + tex_radius = r1; + alpha = 0.75; + break; + case PROP_PERCENTAGE: + r1 = rc->current_value / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; + rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + BLI_snprintf(str, WM_RADIAL_MAX_STR, "%3.1f%%", rc->current_value); + strdrawlen = BLI_strlen_utf8(str); + tex_radius = r1; + alpha = 0.75; + break; + case PROP_FACTOR: + r1 = (1 - rc->current_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; + rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + alpha = rc->current_value / 2.0f + 0.5f; + BLI_snprintf(str, WM_RADIAL_MAX_STR, "%1.3f", rc->current_value); + strdrawlen = BLI_strlen_utf8(str); + break; + case PROP_ANGLE: + r1 = r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; + alpha = 0.75; + rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + BLI_snprintf(str, WM_RADIAL_MAX_STR, "%3.2f", RAD2DEGF(rc->current_value)); + strdrawlen = BLI_strlen_utf8(str); + break; + default: + tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* note, this is a dummy value */ + alpha = 0.75; + break; + } + + /* Keep cursor in the original place */ + x = rc->initial_mouse[0]; + y = rc->initial_mouse[1]; + GPU_matrix_translate_2f((float)x, (float)y); + + GPU_blend(true); + GPU_line_smooth(true); + + /* apply zoom if available */ + if (rc->zoom_prop) { + RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); + GPU_matrix_scale_2fv(zoom); + } + + /* 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); + } + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3fvAlpha(col, 0.5f); + + if (rc->subtype == PROP_ANGLE) { + GPU_matrix_push(); + + /* draw original angle line */ + GPU_matrix_rotate_3f(RAD2DEGF(rc->initial_value), 0.0f, 0.0f, 1.0f); + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f); + immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f); + immEnd(); + + /* draw new angle line */ + GPU_matrix_rotate_3f(RAD2DEGF(rc->current_value - rc->initial_value), 0.0f, 0.0f, 1.0f); + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f); + immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f); + immEnd(); + + GPU_matrix_pop(); + } + + /* draw circles on top */ + imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r1, 40); + imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r2, 40); + if (rmin > 0.0f) { + imm_draw_circle_wire_2d(pos, 0.0, 0.0f, rmin, 40); + } + immUnbindProgram(); + + BLF_size(fontid, 1.5 * fstyle_points * U.pixelsize, U.dpi); + BLF_enable(fontid, BLF_SHADOW); + BLF_shadow(fontid, 3, (const float[4]){0.0f, 0.0f, 0.0f, 0.5f}); + BLF_shadow_offset(fontid, 1, -1); + + /* draw value */ + BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight); + BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f); + BLF_draw(fontid, str, strdrawlen); + + BLF_disable(fontid, BLF_SHADOW); + + GPU_blend(false); + GPU_line_smooth(false); } typedef enum { - RC_PROP_ALLOW_MISSING = 1, - RC_PROP_REQUIRE_FLOAT = 2, - RC_PROP_REQUIRE_BOOL = 4, + RC_PROP_ALLOW_MISSING = 1, + RC_PROP_REQUIRE_FLOAT = 2, + RC_PROP_REQUIRE_BOOL = 4, } RCPropFlags; /** @@ -2260,546 +2405,614 @@ typedef enum { * * \return 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_length, RCPropFlags flags) -{ - PropertyRNA *unused_prop; - int len; - char *str; - - /* check flags */ - if ((flags & RC_PROP_REQUIRE_BOOL) && (flags & RC_PROP_REQUIRE_FLOAT)) { - BKE_report(op->reports, RPT_ERROR, "Property cannot be both boolean and float"); - return 0; - } - - /* get an rna string path from the operator's properties */ - if (!(str = RNA_string_get_alloc(op->ptr, name, NULL, 0))) { - return 1; - } - - if (str[0] == '\0') { - if (r_prop) { - *r_prop = NULL; - } - MEM_freeN(str); - return 1; - } - - if (!r_prop) { - r_prop = &unused_prop; - } - - /* get rna from path */ - if (!RNA_path_resolve(ctx_ptr, str, r_ptr, r_prop)) { - MEM_freeN(str); - if (flags & RC_PROP_ALLOW_MISSING) { - return 1; - } - else { - BKE_reportf(op->reports, RPT_ERROR, "Could not resolve path '%s'", name); - return 0; - } - } - - /* check property type */ - if (flags & (RC_PROP_REQUIRE_BOOL | RC_PROP_REQUIRE_FLOAT)) { - PropertyType prop_type = RNA_property_type(*r_prop); - - if (((flags & RC_PROP_REQUIRE_BOOL) && (prop_type != PROP_BOOLEAN)) || - ((flags & RC_PROP_REQUIRE_FLOAT) && (prop_type != PROP_FLOAT))) - { - MEM_freeN(str); - BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a float", name); - return 0; - } - } - - /* 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; - } - - /* success */ - MEM_freeN(str); - return 1; +static int radial_control_get_path(PointerRNA *ctx_ptr, + wmOperator *op, + const char *name, + PointerRNA *r_ptr, + PropertyRNA **r_prop, + int req_length, + RCPropFlags flags) +{ + PropertyRNA *unused_prop; + int len; + char *str; + + /* check flags */ + if ((flags & RC_PROP_REQUIRE_BOOL) && (flags & RC_PROP_REQUIRE_FLOAT)) { + BKE_report(op->reports, RPT_ERROR, "Property cannot be both boolean and float"); + return 0; + } + + /* get an rna string path from the operator's properties */ + if (!(str = RNA_string_get_alloc(op->ptr, name, NULL, 0))) { + return 1; + } + + if (str[0] == '\0') { + if (r_prop) { + *r_prop = NULL; + } + MEM_freeN(str); + return 1; + } + + if (!r_prop) { + r_prop = &unused_prop; + } + + /* get rna from path */ + if (!RNA_path_resolve(ctx_ptr, str, r_ptr, r_prop)) { + MEM_freeN(str); + if (flags & RC_PROP_ALLOW_MISSING) { + return 1; + } + else { + BKE_reportf(op->reports, RPT_ERROR, "Could not resolve path '%s'", name); + return 0; + } + } + + /* check property type */ + if (flags & (RC_PROP_REQUIRE_BOOL | RC_PROP_REQUIRE_FLOAT)) { + PropertyType prop_type = RNA_property_type(*r_prop); + + if (((flags & RC_PROP_REQUIRE_BOOL) && (prop_type != PROP_BOOLEAN)) || + ((flags & RC_PROP_REQUIRE_FLOAT) && (prop_type != PROP_FLOAT))) { + MEM_freeN(str); + BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a float", name); + return 0; + } + } + + /* 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; + } + + /* success */ + MEM_freeN(str); + return 1; } /* 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, use_secondary_ptr; - PropertyRNA *use_secondary_prop = NULL; - const char *data_path; - - RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr); - - /* check if we use primary or secondary path */ - if (!radial_control_get_path(&ctx_ptr, op, "use_secondary", - &use_secondary_ptr, &use_secondary_prop, - 0, (RC_PROP_ALLOW_MISSING | - RC_PROP_REQUIRE_BOOL))) - { - return 0; - } - else { - if (use_secondary_prop && - RNA_property_boolean_get(&use_secondary_ptr, use_secondary_prop)) - { - data_path = "data_path_secondary"; - } - else { - data_path = "data_path_primary"; - } - } - - if (!radial_control_get_path(&ctx_ptr, op, data_path, &rc->ptr, &rc->prop, 0, 0)) { - return 0; - } - - /* 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, 0, RC_PROP_REQUIRE_FLOAT)) { - return 0; - } - - if (!radial_control_get_path(&ctx_ptr, op, "color_path", &rc->col_ptr, &rc->col_prop, 3, RC_PROP_REQUIRE_FLOAT)) { - return 0; - } - - if (!radial_control_get_path( - &ctx_ptr, op, "fill_color_path", &rc->fill_col_ptr, &rc->fill_col_prop, 3, RC_PROP_REQUIRE_FLOAT)) - { - return 0; - } - - if (!radial_control_get_path( - &ctx_ptr, op, "fill_color_override_path", - &rc->fill_col_override_ptr, &rc->fill_col_override_prop, 3, RC_PROP_REQUIRE_FLOAT)) - { - return 0; - } - if (!radial_control_get_path( - &ctx_ptr, op, "fill_color_override_test_path", - &rc->fill_col_override_test_ptr, &rc->fill_col_override_test_prop, 0, RC_PROP_REQUIRE_BOOL)) - { - 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, 2, - RC_PROP_REQUIRE_FLOAT | RC_PROP_ALLOW_MISSING)) - { - return 0; - } - - if (!radial_control_get_path(&ctx_ptr, op, "image_id", &rc->image_id_ptr, NULL, 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; - } - } - - rc->use_secondary_tex = RNA_boolean_get(op->ptr, "secondary_tex"); - - return 1; + RadialControl *rc = op->customdata; + PointerRNA ctx_ptr, use_secondary_ptr; + PropertyRNA *use_secondary_prop = NULL; + const char *data_path; + + RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr); + + /* check if we use primary or secondary path */ + if (!radial_control_get_path(&ctx_ptr, + op, + "use_secondary", + &use_secondary_ptr, + &use_secondary_prop, + 0, + (RC_PROP_ALLOW_MISSING | RC_PROP_REQUIRE_BOOL))) { + return 0; + } + else { + if (use_secondary_prop && RNA_property_boolean_get(&use_secondary_ptr, use_secondary_prop)) { + data_path = "data_path_secondary"; + } + else { + data_path = "data_path_primary"; + } + } + + if (!radial_control_get_path(&ctx_ptr, op, data_path, &rc->ptr, &rc->prop, 0, 0)) { + return 0; + } + + /* 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, 0, RC_PROP_REQUIRE_FLOAT)) { + return 0; + } + + if (!radial_control_get_path( + &ctx_ptr, op, "color_path", &rc->col_ptr, &rc->col_prop, 3, RC_PROP_REQUIRE_FLOAT)) { + return 0; + } + + if (!radial_control_get_path(&ctx_ptr, + op, + "fill_color_path", + &rc->fill_col_ptr, + &rc->fill_col_prop, + 3, + RC_PROP_REQUIRE_FLOAT)) { + return 0; + } + + if (!radial_control_get_path(&ctx_ptr, + op, + "fill_color_override_path", + &rc->fill_col_override_ptr, + &rc->fill_col_override_prop, + 3, + RC_PROP_REQUIRE_FLOAT)) { + return 0; + } + if (!radial_control_get_path(&ctx_ptr, + op, + "fill_color_override_test_path", + &rc->fill_col_override_test_ptr, + &rc->fill_col_override_test_prop, + 0, + RC_PROP_REQUIRE_BOOL)) { + 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, + 2, + RC_PROP_REQUIRE_FLOAT | RC_PROP_ALLOW_MISSING)) { + return 0; + } + + if (!radial_control_get_path(&ctx_ptr, op, "image_id", &rc->image_id_ptr, NULL, 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; + } + } + + rc->use_secondary_tex = RNA_boolean_get(op->ptr, "secondary_tex"); + + return 1; } static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - wmWindowManager *wm; - RadialControl *rc; - - - if (!(op->customdata = rc = MEM_callocN(sizeof(RadialControl), "RadialControl"))) { - return OPERATOR_CANCELLED; - } - - if (!radial_control_get_properties(C, op)) { - MEM_freeN(rc); - return OPERATOR_CANCELLED; - } - - /* get type, initial, min, and max values of the property */ - switch ((rc->type = RNA_property_type(rc->prop))) { - case PROP_INT: - { - int value, min, max, step; - - value = RNA_property_int_get(&rc->ptr, rc->prop); - RNA_property_int_ui_range(&rc->ptr, rc->prop, &min, &max, &step); - - rc->initial_value = value; - rc->min_value = min_ii(value, min); - rc->max_value = max_ii(value, max); - break; - } - case PROP_FLOAT: - { - float value, min, max, step, precision; - - value = RNA_property_float_get(&rc->ptr, rc->prop); - RNA_property_float_ui_range(&rc->ptr, rc->prop, &min, &max, &step, &precision); - - rc->initial_value = value; - rc->min_value = min_ff(value, min); - rc->max_value = max_ff(value, max); - break; - } - default: - BKE_report(op->reports, RPT_ERROR, "Property must be an integer or a float"); - MEM_freeN(rc); - return OPERATOR_CANCELLED; - } - - /* initialize numerical input */ - initNumInput(&rc->num_input); - rc->num_input.idx_max = 0; - rc->num_input.val_flag[0] |= NUM_NO_NEGATIVE; - rc->num_input.unit_sys = USER_UNIT_NONE; - rc->num_input.unit_type[0] = B_UNIT_LENGTH; - - /* get subtype of property */ - rc->subtype = RNA_property_subtype(rc->prop); - if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_PERCENTAGE, PROP_ANGLE, PROP_PIXEL)) { - BKE_report(op->reports, RPT_ERROR, "Property must be a none, distance, factor, percentage, angle, or pixel"); - MEM_freeN(rc); - return OPERATOR_CANCELLED; - } - - rc->current_value = rc->initial_value; - radial_control_set_initial_mouse(rc, event); - radial_control_set_tex(rc); - - /* temporarily disable other paint cursors */ - wm = CTX_wm_manager(C); - rc->orig_paintcursors = wm->paintcursors; - BLI_listbase_clear(&wm->paintcursors); - - /* add radial control paint cursor */ - rc->cursor = WM_paint_cursor_activate( - wm, - SPACE_TYPE_ANY, RGN_TYPE_ANY, - op->type->poll, - radial_control_paint_cursor, rc); - - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; + wmWindowManager *wm; + RadialControl *rc; + + if (!(op->customdata = rc = MEM_callocN(sizeof(RadialControl), "RadialControl"))) { + return OPERATOR_CANCELLED; + } + + if (!radial_control_get_properties(C, op)) { + MEM_freeN(rc); + return OPERATOR_CANCELLED; + } + + /* get type, initial, min, and max values of the property */ + switch ((rc->type = RNA_property_type(rc->prop))) { + case PROP_INT: { + int value, min, max, step; + + value = RNA_property_int_get(&rc->ptr, rc->prop); + RNA_property_int_ui_range(&rc->ptr, rc->prop, &min, &max, &step); + + rc->initial_value = value; + rc->min_value = min_ii(value, min); + rc->max_value = max_ii(value, max); + break; + } + case PROP_FLOAT: { + float value, min, max, step, precision; + + value = RNA_property_float_get(&rc->ptr, rc->prop); + RNA_property_float_ui_range(&rc->ptr, rc->prop, &min, &max, &step, &precision); + + rc->initial_value = value; + rc->min_value = min_ff(value, min); + rc->max_value = max_ff(value, max); + break; + } + default: + BKE_report(op->reports, RPT_ERROR, "Property must be an integer or a float"); + MEM_freeN(rc); + return OPERATOR_CANCELLED; + } + + /* initialize numerical input */ + initNumInput(&rc->num_input); + rc->num_input.idx_max = 0; + rc->num_input.val_flag[0] |= NUM_NO_NEGATIVE; + rc->num_input.unit_sys = USER_UNIT_NONE; + rc->num_input.unit_type[0] = B_UNIT_LENGTH; + + /* get subtype of property */ + rc->subtype = RNA_property_subtype(rc->prop); + if (!ELEM(rc->subtype, + PROP_NONE, + PROP_DISTANCE, + PROP_FACTOR, + PROP_PERCENTAGE, + PROP_ANGLE, + PROP_PIXEL)) { + BKE_report(op->reports, + RPT_ERROR, + "Property must be a none, distance, factor, percentage, angle, or pixel"); + MEM_freeN(rc); + return OPERATOR_CANCELLED; + } + + rc->current_value = rc->initial_value; + radial_control_set_initial_mouse(rc, event); + radial_control_set_tex(rc); + + /* temporarily disable other paint cursors */ + wm = CTX_wm_manager(C); + rc->orig_paintcursors = wm->paintcursors; + BLI_listbase_clear(&wm->paintcursors); + + /* add radial control paint cursor */ + rc->cursor = WM_paint_cursor_activate( + wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, op->type->poll, radial_control_paint_cursor, rc); + + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; } 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; - } + 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 void radial_control_cancel(bContext *C, wmOperator *op) { - RadialControl *rc = op->customdata; - wmWindowManager *wm = CTX_wm_manager(C); - ScrArea *sa = CTX_wm_area(C); + RadialControl *rc = op->customdata; + wmWindowManager *wm = CTX_wm_manager(C); + ScrArea *sa = CTX_wm_area(C); - if (rc->dial) { - MEM_freeN(rc->dial); - rc->dial = NULL; - } + if (rc->dial) { + MEM_freeN(rc->dial); + rc->dial = NULL; + } - ED_area_status_text(sa, NULL); + ED_area_status_text(sa, NULL); - WM_paint_cursor_end(wm, rc->cursor); + WM_paint_cursor_end(wm, rc->cursor); - /* restore original paint cursors */ - wm->paintcursors = rc->orig_paintcursors; + /* 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); + /* 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); + glDeleteTextures(1, &rc->gltex); - MEM_freeN(rc); + MEM_freeN(rc); } static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *event) { - RadialControl *rc = op->customdata; - float new_value, dist = 0.0f, zoom[2]; - float delta[2], ret = OPERATOR_RUNNING_MODAL; - bool snap; - float angle_precision = 0.0f; - const bool has_numInput = hasNumInput(&rc->num_input); - bool handled = false; - float numValue; - /* TODO: fix hardcoded events */ - - snap = event->ctrl != 0; - - /* Modal numinput active, try to handle numeric inputs first... */ - if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) { - handled = true; - applyNumInput(&rc->num_input, &numValue); - - if (rc->subtype == PROP_ANGLE) { - numValue = DEG2RADF(numValue); - numValue = fmod(numValue, 2.0f * (float)M_PI); - if (numValue < 0.0f) { - numValue += 2.0f * (float)M_PI; - } - } - - CLAMP(numValue, rc->min_value, rc->max_value); - new_value = numValue; - - radial_control_set_value(rc, new_value); - rc->current_value = new_value; - radial_control_update_header(op, C); - return OPERATOR_RUNNING_MODAL; - } - else { - handled = false; - switch (event->type) { - case ESCKEY: - case RIGHTMOUSE: - /* canceled; restore original value */ - radial_control_set_value(rc, rc->initial_value); - ret = OPERATOR_CANCELLED; - break; - - case LEFTMOUSE: - case PADENTER: - case RETKEY: - /* done; value already set */ - RNA_property_update(C, &rc->ptr, rc->prop); - ret = OPERATOR_FINISHED; - break; - - case MOUSEMOVE: - if (!has_numInput) { - if (rc->slow_mode) { - if (rc->subtype == PROP_ANGLE) { - float position[2] = {event->x, event->y}; - - /* calculate the initial angle here first */ - delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0]; - delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1]; - - /* precision angle gets calculated from dial and gets added later */ - angle_precision = -0.1f * BLI_dial_angle(rc->dial, position); - } - else { - delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0]; - delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1]; - - 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 = len_v2(delta); - - delta[0] = event->x - rc->slow_mouse[0]; - delta[1] = event->y - rc->slow_mouse[1]; - - if (rc->zoom_prop) { - delta[0] /= zoom[0]; - delta[1] /= zoom[1]; - } - - dist = dist + 0.1f * (delta[0] + delta[1]); - } - } - else { - delta[0] = rc->initial_mouse[0] - event->x; - delta[1] = rc->initial_mouse[1] - event->y; - - 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 = len_v2(delta); - } - - /* calculate new value and apply snapping */ - switch (rc->subtype) { - case PROP_NONE: - case PROP_DISTANCE: - case PROP_PIXEL: - new_value = dist; - if (snap) { - new_value = ((int)new_value + 5) / 10 * 10; - } - break; - case PROP_PERCENTAGE: - new_value = ((dist - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) / WM_RADIAL_CONTROL_DISPLAY_WIDTH) * 100.0f; - if (snap) { - new_value = ((int)(new_value + 2.5f)) / 5 * 5; - } - break; - case PROP_FACTOR: - new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH; - if (snap) { - new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f; - } - break; - case PROP_ANGLE: - new_value = atan2f(delta[1], delta[0]) + (float)M_PI + angle_precision; - new_value = fmod(new_value, 2.0f * (float)M_PI); - if (new_value < 0.0f) { - new_value += 2.0f * (float)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; - handled = true; - break; - } - break; - - case LEFTSHIFTKEY: - case RIGHTSHIFTKEY: - { - if (event->val == KM_PRESS) { - rc->slow_mouse[0] = event->x; - rc->slow_mouse[1] = event->y; - rc->slow_mode = true; - if (rc->subtype == PROP_ANGLE) { - float initial_position[2] = {UNPACK2(rc->initial_mouse)}; - float current_position[2] = {UNPACK2(rc->slow_mouse)}; - rc->dial = BLI_dial_initialize(initial_position, 0.0f); - /* immediately set the position to get a an initial direction */ - BLI_dial_angle(rc->dial, current_position); - } - handled = true; - } - if (event->val == KM_RELEASE) { - rc->slow_mode = false; - handled = true; - if (rc->dial) { - MEM_freeN(rc->dial); - rc->dial = NULL; - } - } - break; - } - } - - /* Modal numinput inactive, try to handle numeric inputs last... */ - if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) { - applyNumInput(&rc->num_input, &numValue); - - if (rc->subtype == PROP_ANGLE) { - numValue = DEG2RADF(numValue); - numValue = fmod(numValue, 2.0f * (float)M_PI); - if (numValue < 0.0f) { - numValue += 2.0f * (float)M_PI; - } - } - - CLAMP(numValue, rc->min_value, rc->max_value); - new_value = numValue; - - radial_control_set_value(rc, new_value); - - rc->current_value = new_value; - radial_control_update_header(op, C); - return OPERATOR_RUNNING_MODAL; - } - } - - ED_region_tag_redraw(CTX_wm_region(C)); - radial_control_update_header(op, C); - - if (ret != OPERATOR_RUNNING_MODAL) { - radial_control_cancel(C, op); - } - - return ret; + RadialControl *rc = op->customdata; + float new_value, dist = 0.0f, zoom[2]; + float delta[2], ret = OPERATOR_RUNNING_MODAL; + bool snap; + float angle_precision = 0.0f; + const bool has_numInput = hasNumInput(&rc->num_input); + bool handled = false; + float numValue; + /* TODO: fix hardcoded events */ + + snap = event->ctrl != 0; + + /* Modal numinput active, try to handle numeric inputs first... */ + if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) { + handled = true; + applyNumInput(&rc->num_input, &numValue); + + if (rc->subtype == PROP_ANGLE) { + numValue = DEG2RADF(numValue); + numValue = fmod(numValue, 2.0f * (float)M_PI); + if (numValue < 0.0f) { + numValue += 2.0f * (float)M_PI; + } + } + + CLAMP(numValue, rc->min_value, rc->max_value); + new_value = numValue; + + radial_control_set_value(rc, new_value); + rc->current_value = new_value; + radial_control_update_header(op, C); + return OPERATOR_RUNNING_MODAL; + } + else { + handled = false; + switch (event->type) { + case ESCKEY: + case RIGHTMOUSE: + /* canceled; restore original value */ + radial_control_set_value(rc, rc->initial_value); + ret = OPERATOR_CANCELLED; + break; + + case LEFTMOUSE: + case PADENTER: + case RETKEY: + /* done; value already set */ + RNA_property_update(C, &rc->ptr, rc->prop); + ret = OPERATOR_FINISHED; + break; + + case MOUSEMOVE: + if (!has_numInput) { + if (rc->slow_mode) { + if (rc->subtype == PROP_ANGLE) { + float position[2] = {event->x, event->y}; + + /* calculate the initial angle here first */ + delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0]; + delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1]; + + /* precision angle gets calculated from dial and gets added later */ + angle_precision = -0.1f * BLI_dial_angle(rc->dial, position); + } + else { + delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0]; + delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1]; + + 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 = len_v2(delta); + + delta[0] = event->x - rc->slow_mouse[0]; + delta[1] = event->y - rc->slow_mouse[1]; + + if (rc->zoom_prop) { + delta[0] /= zoom[0]; + delta[1] /= zoom[1]; + } + + dist = dist + 0.1f * (delta[0] + delta[1]); + } + } + else { + delta[0] = rc->initial_mouse[0] - event->x; + delta[1] = rc->initial_mouse[1] - event->y; + + 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 = len_v2(delta); + } + + /* calculate new value and apply snapping */ + switch (rc->subtype) { + case PROP_NONE: + case PROP_DISTANCE: + case PROP_PIXEL: + new_value = dist; + if (snap) { + new_value = ((int)new_value + 5) / 10 * 10; + } + break; + case PROP_PERCENTAGE: + new_value = ((dist - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) / + WM_RADIAL_CONTROL_DISPLAY_WIDTH) * + 100.0f; + if (snap) { + new_value = ((int)(new_value + 2.5f)) / 5 * 5; + } + break; + case PROP_FACTOR: + new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / + WM_RADIAL_CONTROL_DISPLAY_WIDTH; + if (snap) { + new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f; + } + break; + case PROP_ANGLE: + new_value = atan2f(delta[1], delta[0]) + (float)M_PI + angle_precision; + new_value = fmod(new_value, 2.0f * (float)M_PI); + if (new_value < 0.0f) { + new_value += 2.0f * (float)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; + handled = true; + break; + } + break; + + case LEFTSHIFTKEY: + case RIGHTSHIFTKEY: { + if (event->val == KM_PRESS) { + rc->slow_mouse[0] = event->x; + rc->slow_mouse[1] = event->y; + rc->slow_mode = true; + if (rc->subtype == PROP_ANGLE) { + float initial_position[2] = {UNPACK2(rc->initial_mouse)}; + float current_position[2] = {UNPACK2(rc->slow_mouse)}; + rc->dial = BLI_dial_initialize(initial_position, 0.0f); + /* immediately set the position to get a an initial direction */ + BLI_dial_angle(rc->dial, current_position); + } + handled = true; + } + if (event->val == KM_RELEASE) { + rc->slow_mode = false; + handled = true; + if (rc->dial) { + MEM_freeN(rc->dial); + rc->dial = NULL; + } + } + break; + } + } + + /* Modal numinput inactive, try to handle numeric inputs last... */ + if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) { + applyNumInput(&rc->num_input, &numValue); + + if (rc->subtype == PROP_ANGLE) { + numValue = DEG2RADF(numValue); + numValue = fmod(numValue, 2.0f * (float)M_PI); + if (numValue < 0.0f) { + numValue += 2.0f * (float)M_PI; + } + } + + CLAMP(numValue, rc->min_value, rc->max_value); + new_value = numValue; + + radial_control_set_value(rc, new_value); + + rc->current_value = new_value; + radial_control_update_header(op, C); + return OPERATOR_RUNNING_MODAL; + } + } + + ED_region_tag_redraw(CTX_wm_region(C)); + radial_control_update_header(op, 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"; - ot->description = "Set some size property (like e.g. brush size) with mouse wheel"; - - ot->invoke = radial_control_invoke; - ot->modal = radial_control_modal; - ot->cancel = radial_control_cancel; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; - - /* all paths relative to the context */ - PropertyRNA *prop; - prop = RNA_def_string(ot->srna, "data_path_primary", NULL, 0, "Primary Data Path", "Primary path of property to be set by the radial control"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_string(ot->srna, "data_path_secondary", NULL, 0, "Secondary Data Path", "Secondary path of property to be set by the radial control"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_string(ot->srna, "use_secondary", NULL, 0, "Use Secondary", "Path of property to select between the primary and secondary data paths"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_string(ot->srna, "rotation_path", NULL, 0, "Rotation Path", "Path of property used to rotate the texture display"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_string(ot->srna, "color_path", NULL, 0, "Color Path", "Path of property used to set the color of the control"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_string(ot->srna, "fill_color_path", NULL, 0, "Fill Color Path", "Path of property used to set the fill color of the control"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_string(ot->srna, "fill_color_override_path", NULL, 0, "Fill Color Override Path", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_string(ot->srna, "fill_color_override_test_path", NULL, 0, "Fill Color Override Test", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_string(ot->srna, "zoom_path", NULL, 0, "Zoom Path", "Path of property used to set the zoom level for the control"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_boolean(ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + ot->name = "Radial Control"; + ot->idname = "WM_OT_radial_control"; + ot->description = "Set some size property (like e.g. brush size) with mouse wheel"; + + ot->invoke = radial_control_invoke; + ot->modal = radial_control_modal; + ot->cancel = radial_control_cancel; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* all paths relative to the context */ + PropertyRNA *prop; + prop = RNA_def_string(ot->srna, + "data_path_primary", + NULL, + 0, + "Primary Data Path", + "Primary path of property to be set by the radial control"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_string(ot->srna, + "data_path_secondary", + NULL, + 0, + "Secondary Data Path", + "Secondary path of property to be set by the radial control"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_string(ot->srna, + "use_secondary", + NULL, + 0, + "Use Secondary", + "Path of property to select between the primary and secondary data paths"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_string(ot->srna, + "rotation_path", + NULL, + 0, + "Rotation Path", + "Path of property used to rotate the texture display"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_string(ot->srna, + "color_path", + NULL, + 0, + "Color Path", + "Path of property used to set the color of the control"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_string(ot->srna, + "fill_color_path", + NULL, + 0, + "Fill Color Path", + "Path of property used to set the fill color of the control"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_string( + ot->srna, "fill_color_override_path", NULL, 0, "Fill Color Override Path", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_string( + ot->srna, "fill_color_override_test_path", NULL, 0, "Fill Color Override Test", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_string(ot->srna, + "zoom_path", + NULL, + 0, + "Zoom Path", + "Path of property used to set the zoom level for the control"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_string(ot->srna, + "image_id", + NULL, + 0, + "Image ID", + "Path of ID that is used to generate an image for the control"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_boolean( + ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ************************** timer for testing ***************** */ @@ -2808,273 +3021,293 @@ static void WM_OT_radial_control(wmOperatorType *ot) static void redraw_timer_window_swap(bContext *C) { - wmWindow *win = CTX_wm_window(C); - ScrArea *sa; - CTX_wm_menu_set(C, NULL); + wmWindow *win = CTX_wm_window(C); + ScrArea *sa; + CTX_wm_menu_set(C, NULL); - for (sa = CTX_wm_screen(C)->areabase.first; sa; sa = sa->next) { - ED_area_tag_redraw(sa); - } - wm_draw_update(C); + for (sa = CTX_wm_screen(C)->areabase.first; sa; sa = sa->next) { + ED_area_tag_redraw(sa); + } + wm_draw_update(C); - CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ + CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ } enum { - eRTDrawRegion = 0, - eRTDrawRegionSwap = 1, - eRTDrawWindow = 2, - eRTDrawWindowSwap = 3, - eRTAnimationStep = 4, - eRTAnimationPlay = 5, - eRTUndo = 6, + eRTDrawRegion = 0, + eRTDrawRegionSwap = 1, + eRTDrawWindow = 2, + eRTDrawWindowSwap = 3, + eRTAnimationStep = 4, + eRTAnimationPlay = 5, + eRTUndo = 6, }; static const EnumPropertyItem redraw_timer_type_items[] = { - {eRTDrawRegion, "DRAW", 0, "Draw Region", "Draw Region"}, - {eRTDrawRegionSwap, "DRAW_SWAP", 0, "Draw Region + Swap", "Draw Region and Swap"}, - {eRTDrawWindow, "DRAW_WIN", 0, "Draw Window", "Draw Window"}, - {eRTDrawWindowSwap, "DRAW_WIN_SWAP", 0, "Draw Window + Swap", "Draw Window and Swap"}, - {eRTAnimationStep, "ANIM_STEP", 0, "Anim Step", "Animation Steps"}, - {eRTAnimationPlay, "ANIM_PLAY", 0, "Anim Play", "Animation Playback"}, - {eRTUndo, "UNDO", 0, "Undo/Redo", "Undo/Redo"}, - {0, NULL, 0, NULL, NULL}, + {eRTDrawRegion, "DRAW", 0, "Draw Region", "Draw Region"}, + {eRTDrawRegionSwap, "DRAW_SWAP", 0, "Draw Region + Swap", "Draw Region and Swap"}, + {eRTDrawWindow, "DRAW_WIN", 0, "Draw Window", "Draw Window"}, + {eRTDrawWindowSwap, "DRAW_WIN_SWAP", 0, "Draw Window + Swap", "Draw Window and Swap"}, + {eRTAnimationStep, "ANIM_STEP", 0, "Anim Step", "Animation Steps"}, + {eRTAnimationPlay, "ANIM_PLAY", 0, "Anim Play", "Animation Playback"}, + {eRTUndo, "UNDO", 0, "Undo/Redo", "Undo/Redo"}, + {0, NULL, 0, NULL, NULL}, }; - -static void redraw_timer_step( - bContext *C, Main *bmain, Scene *scene, - struct Depsgraph *depsgraph, - wmWindow *win, ScrArea *sa, ARegion *ar, - const int type, const int cfra) -{ - if (type == eRTDrawRegion) { - if (ar) { - ED_region_do_draw(C, ar); - ar->do_draw = false; - } - } - else if (type == eRTDrawRegionSwap) { - CTX_wm_menu_set(C, NULL); - - ED_region_tag_redraw(ar); - wm_draw_update(C); - - CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ - } - else if (type == eRTDrawWindow) { - bScreen *screen = WM_window_get_active_screen(win); - ScrArea *sa_iter; - - CTX_wm_menu_set(C, NULL); - - for (sa_iter = screen->areabase.first; sa_iter; sa_iter = sa_iter->next) { - ARegion *ar_iter; - CTX_wm_area_set(C, sa_iter); - - for (ar_iter = sa_iter->regionbase.first; ar_iter; ar_iter = ar_iter->next) { - if (ar_iter->visible) { - CTX_wm_region_set(C, ar_iter); - ED_region_do_draw(C, ar_iter); - ar_iter->do_draw = false; - } - } - } - - CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ - - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); - } - else if (type == eRTDrawWindowSwap) { - redraw_timer_window_swap(C); - } - else if (type == eRTAnimationStep) { - scene->r.cfra += (cfra == scene->r.cfra) ? 1 : -1; - BKE_scene_graph_update_for_newframe(depsgraph, bmain); - } - else if (type == eRTAnimationPlay) { - /* play anim, return on same frame as started with */ - int tot = (scene->r.efra - scene->r.sfra) + 1; - - while (tot--) { - /* todo, ability to escape! */ - scene->r.cfra++; - if (scene->r.cfra > scene->r.efra) { - scene->r.cfra = scene->r.sfra; - } - - BKE_scene_graph_update_for_newframe(depsgraph, bmain); - redraw_timer_window_swap(C); - } - } - else { /* eRTUndo */ - ED_undo_pop(C); - ED_undo_redo(C); - } +static void redraw_timer_step(bContext *C, + Main *bmain, + Scene *scene, + struct Depsgraph *depsgraph, + wmWindow *win, + ScrArea *sa, + ARegion *ar, + const int type, + const int cfra) +{ + if (type == eRTDrawRegion) { + if (ar) { + ED_region_do_draw(C, ar); + ar->do_draw = false; + } + } + else if (type == eRTDrawRegionSwap) { + CTX_wm_menu_set(C, NULL); + + ED_region_tag_redraw(ar); + wm_draw_update(C); + + CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ + } + else if (type == eRTDrawWindow) { + bScreen *screen = WM_window_get_active_screen(win); + ScrArea *sa_iter; + + CTX_wm_menu_set(C, NULL); + + for (sa_iter = screen->areabase.first; sa_iter; sa_iter = sa_iter->next) { + ARegion *ar_iter; + CTX_wm_area_set(C, sa_iter); + + for (ar_iter = sa_iter->regionbase.first; ar_iter; ar_iter = ar_iter->next) { + if (ar_iter->visible) { + CTX_wm_region_set(C, ar_iter); + ED_region_do_draw(C, ar_iter); + ar_iter->do_draw = false; + } + } + } + + CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ + + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + } + else if (type == eRTDrawWindowSwap) { + redraw_timer_window_swap(C); + } + else if (type == eRTAnimationStep) { + scene->r.cfra += (cfra == scene->r.cfra) ? 1 : -1; + BKE_scene_graph_update_for_newframe(depsgraph, bmain); + } + else if (type == eRTAnimationPlay) { + /* play anim, return on same frame as started with */ + int tot = (scene->r.efra - scene->r.sfra) + 1; + + while (tot--) { + /* todo, ability to escape! */ + scene->r.cfra++; + if (scene->r.cfra > scene->r.efra) { + scene->r.cfra = scene->r.sfra; + } + + BKE_scene_graph_update_for_newframe(depsgraph, bmain); + redraw_timer_window_swap(C); + } + } + else { /* eRTUndo */ + ED_undo_pop(C); + ED_undo_redo(C); + } } static int redraw_timer_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); - double time_start, time_delta; - const int type = RNA_enum_get(op->ptr, "type"); - const int iter = RNA_int_get(op->ptr, "iterations"); - const double time_limit = (double)RNA_float_get(op->ptr, "time_limit"); - const int cfra = scene->r.cfra; - int a, iter_steps = 0; - const char *infostr = ""; - struct Depsgraph *depsgraph = CTX_data_depsgraph(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + double time_start, time_delta; + const int type = RNA_enum_get(op->ptr, "type"); + const int iter = RNA_int_get(op->ptr, "iterations"); + const double time_limit = (double)RNA_float_get(op->ptr, "time_limit"); + const int cfra = scene->r.cfra; + int a, iter_steps = 0; + const char *infostr = ""; + struct Depsgraph *depsgraph = CTX_data_depsgraph(C); - WM_cursor_wait(1); + WM_cursor_wait(1); - time_start = PIL_check_seconds_timer(); + time_start = PIL_check_seconds_timer(); - for (a = 0; a < iter; a++) { - redraw_timer_step(C, bmain, scene, depsgraph, win, sa, ar, type, cfra); - iter_steps += 1; + for (a = 0; a < iter; a++) { + redraw_timer_step(C, bmain, scene, depsgraph, win, sa, ar, type, cfra); + iter_steps += 1; - if (time_limit != 0.0) { - if ((PIL_check_seconds_timer() - time_start) > time_limit) { - break; - } - a = 0; - } - } + if (time_limit != 0.0) { + if ((PIL_check_seconds_timer() - time_start) > time_limit) { + break; + } + a = 0; + } + } - time_delta = (PIL_check_seconds_timer() - time_start) * 1000; + time_delta = (PIL_check_seconds_timer() - time_start) * 1000; - RNA_enum_description(redraw_timer_type_items, type, &infostr); + RNA_enum_description(redraw_timer_type_items, type, &infostr); - WM_cursor_wait(0); + WM_cursor_wait(0); - BKE_reportf(op->reports, RPT_WARNING, - "%d x %s: %.4f ms, average: %.8f ms", - iter_steps, infostr, time_delta, time_delta / iter_steps); + BKE_reportf(op->reports, + RPT_WARNING, + "%d x %s: %.4f ms, average: %.8f ms", + iter_steps, + infostr, + time_delta, + time_delta / iter_steps); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void WM_OT_redraw_timer(wmOperatorType *ot) { - ot->name = "Redraw Timer"; - ot->idname = "WM_OT_redraw_timer"; - ot->description = "Simple redraw timer to test the speed of updating the interface"; + ot->name = "Redraw Timer"; + ot->idname = "WM_OT_redraw_timer"; + ot->description = "Simple redraw timer to test the speed of updating the interface"; - ot->invoke = WM_menu_invoke; - ot->exec = redraw_timer_exec; - ot->poll = WM_operator_winactive; - - ot->prop = RNA_def_enum(ot->srna, "type", redraw_timer_type_items, eRTDrawRegion, "Type", ""); - RNA_def_int(ot->srna, "iterations", 10, 1, INT_MAX, "Iterations", "Number of times to redraw", 1, 1000); - RNA_def_float(ot->srna, "time_limit", 0.0, 0.0, FLT_MAX, - "Time Limit", "Seconds to run the test for (override iterations)", 0.0, 60.0); + ot->invoke = WM_menu_invoke; + ot->exec = redraw_timer_exec; + ot->poll = WM_operator_winactive; + ot->prop = RNA_def_enum(ot->srna, "type", redraw_timer_type_items, eRTDrawRegion, "Type", ""); + RNA_def_int( + ot->srna, "iterations", 10, 1, INT_MAX, "Iterations", "Number of times to redraw", 1, 1000); + RNA_def_float(ot->srna, + "time_limit", + 0.0, + 0.0, + FLT_MAX, + "Time Limit", + "Seconds to run the test for (override iterations)", + 0.0, + 60.0); } /* ************************** memory statistics for testing ***************** */ static int memory_statistics_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { - MEM_printmemlist_stats(); - return OPERATOR_FINISHED; + MEM_printmemlist_stats(); + return OPERATOR_FINISHED; } static void WM_OT_memory_statistics(wmOperatorType *ot) { - ot->name = "Memory Statistics"; - ot->idname = "WM_OT_memory_statistics"; - ot->description = "Print memory statistics to the console"; + ot->name = "Memory Statistics"; + ot->idname = "WM_OT_memory_statistics"; + ot->description = "Print memory statistics to the console"; - ot->exec = memory_statistics_exec; + ot->exec = memory_statistics_exec; } /* *************************** Mat/tex/etc. previews generation ************* */ typedef struct PreviewsIDEnsureData { - bContext *C; - Scene *scene; + bContext *C; + Scene *scene; } PreviewsIDEnsureData; static void previews_id_ensure(bContext *C, Scene *scene, ID *id) { - BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)); + BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)); - /* Only preview non-library datablocks, lib ones do not pertain to this .blend file! - * Same goes for ID with no user. */ - if (!ID_IS_LINKED(id) && (id->us != 0)) { - UI_id_icon_render(C, scene, id, false, false); - UI_id_icon_render(C, scene, id, true, false); - } + /* Only preview non-library datablocks, lib ones do not pertain to this .blend file! + * Same goes for ID with no user. */ + if (!ID_IS_LINKED(id) && (id->us != 0)) { + UI_id_icon_render(C, scene, id, false, false); + UI_id_icon_render(C, scene, id, true, false); + } } -static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int cb_flag) +static int previews_id_ensure_callback(void *userdata, + ID *UNUSED(self_id), + ID **idptr, + int cb_flag) { - if (cb_flag & IDWALK_CB_PRIVATE) { - return IDWALK_RET_NOP; - } + if (cb_flag & IDWALK_CB_PRIVATE) { + return IDWALK_RET_NOP; + } - PreviewsIDEnsureData *data = userdata; - ID *id = *idptr; + PreviewsIDEnsureData *data = userdata; + ID *id = *idptr; - if (id && (id->tag & LIB_TAG_DOIT)) { - BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)); - previews_id_ensure(data->C, data->scene, id); - id->tag &= ~LIB_TAG_DOIT; - } + if (id && (id->tag & LIB_TAG_DOIT)) { + BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)); + previews_id_ensure(data->C, data->scene, id); + id->tag &= ~LIB_TAG_DOIT; + } - return IDWALK_RET_NOP; + return IDWALK_RET_NOP; } static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - ListBase *lb[] = {&bmain->materials, &bmain->textures, &bmain->images, &bmain->worlds, &bmain->lights, NULL}; - PreviewsIDEnsureData preview_id_data; - Scene *scene; - ID *id; - int i; - - /* We use LIB_TAG_DOIT to check whether we have already handled a given ID or not. */ - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - for (i = 0; lb[i]; i++) { - BKE_main_id_tag_listbase(lb[i], LIB_TAG_DOIT, true); - } - - preview_id_data.C = C; - for (scene = bmain->scenes.first; scene; scene = scene->id.next) { - preview_id_data.scene = scene; - id = (ID *)scene; - - BKE_library_foreach_ID_link(NULL, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE); - } - - /* Check a last time for ID not used (fake users only, in theory), and - * do our best for those, using current scene... */ - for (i = 0; lb[i]; i++) { - for (id = lb[i]->first; id; id = id->next) { - if (id->tag & LIB_TAG_DOIT) { - previews_id_ensure(C, NULL, id); - id->tag &= ~LIB_TAG_DOIT; - } - } - } - - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + ListBase *lb[] = { + &bmain->materials, &bmain->textures, &bmain->images, &bmain->worlds, &bmain->lights, NULL}; + PreviewsIDEnsureData preview_id_data; + Scene *scene; + ID *id; + int i; + + /* We use LIB_TAG_DOIT to check whether we have already handled a given ID or not. */ + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + for (i = 0; lb[i]; i++) { + BKE_main_id_tag_listbase(lb[i], LIB_TAG_DOIT, true); + } + + preview_id_data.C = C; + for (scene = bmain->scenes.first; scene; scene = scene->id.next) { + preview_id_data.scene = scene; + id = (ID *)scene; + + BKE_library_foreach_ID_link( + NULL, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE); + } + + /* Check a last time for ID not used (fake users only, in theory), and + * do our best for those, using current scene... */ + for (i = 0; lb[i]; i++) { + for (id = lb[i]->first; id; id = id->next) { + if (id->tag & LIB_TAG_DOIT) { + previews_id_ensure(C, NULL, id); + id->tag &= ~LIB_TAG_DOIT; + } + } + } + + return OPERATOR_FINISHED; } static void WM_OT_previews_ensure(wmOperatorType *ot) { - ot->name = "Refresh Data-Block Previews"; - ot->idname = "WM_OT_previews_ensure"; - ot->description = "Ensure data-block previews are available and up-to-date " - "(to be saved in .blend file, only for some types like materials, textures, etc.)"; + ot->name = "Refresh Data-Block Previews"; + ot->idname = "WM_OT_previews_ensure"; + ot->description = + "Ensure data-block previews are available and up-to-date " + "(to be saved in .blend file, only for some types like materials, textures, etc.)"; - ot->exec = previews_ensure_exec; + ot->exec = previews_ensure_exec; } /* *************************** Datablocks previews clear ************* */ @@ -3089,7 +3322,7 @@ static const EnumPropertyItem preview_id_type_items[] = { {FILTER_ID_WO, "WORLD", 0, "Worlds", ""}, {FILTER_ID_TE, "TEXTURE", 0, "Textures", ""}, {FILTER_ID_IM, "IMAGE", 0, "Images", ""}, -#if 0 /* XXX TODO */ +#if 0 /* XXX TODO */ {FILTER_ID_BR, "BRUSH", 0, "Brushes", ""}, #endif {0, NULL, 0, NULL, NULL}, @@ -3097,315 +3330,346 @@ static const EnumPropertyItem preview_id_type_items[] = { static int previews_clear_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - ListBase *lb[] = {&bmain->objects, &bmain->collections, - &bmain->materials, &bmain->worlds, &bmain->lights, &bmain->textures, &bmain->images, NULL}; - int i; + Main *bmain = CTX_data_main(C); + ListBase *lb[] = {&bmain->objects, + &bmain->collections, + &bmain->materials, + &bmain->worlds, + &bmain->lights, + &bmain->textures, + &bmain->images, + NULL}; + int i; - const int id_filters = RNA_enum_get(op->ptr, "id_type"); + const int id_filters = RNA_enum_get(op->ptr, "id_type"); - for (i = 0; lb[i]; i++) { - ID *id = lb[i]->first; - if (!id) { - continue; - } + for (i = 0; lb[i]; i++) { + ID *id = lb[i]->first; + if (!id) { + continue; + } -// printf("%s: %d, %d, %d -> %d\n", id->name, GS(id->name), BKE_idcode_to_idfilter(GS(id->name)), -// id_filters, BKE_idcode_to_idfilter(GS(id->name)) & id_filters); + // printf("%s: %d, %d, %d -> %d\n", id->name, GS(id->name), BKE_idcode_to_idfilter(GS(id->name)), + // id_filters, BKE_idcode_to_idfilter(GS(id->name)) & id_filters); - if (!id || !(BKE_idcode_to_idfilter(GS(id->name)) & id_filters)) { - continue; - } + if (!id || !(BKE_idcode_to_idfilter(GS(id->name)) & id_filters)) { + continue; + } - for (; id; id = id->next) { - PreviewImage *prv_img = BKE_previewimg_id_ensure(id); + for (; id; id = id->next) { + PreviewImage *prv_img = BKE_previewimg_id_ensure(id); - BKE_previewimg_clear(prv_img); - } - } + BKE_previewimg_clear(prv_img); + } + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void WM_OT_previews_clear(wmOperatorType *ot) { - ot->name = "Clear Data-Block Previews"; - ot->idname = "WM_OT_previews_clear"; - ot->description = "Clear data-block previews (only for some types like objects, materials, textures, etc.)"; + ot->name = "Clear Data-Block Previews"; + ot->idname = "WM_OT_previews_clear"; + ot->description = + "Clear data-block previews (only for some types like objects, materials, textures, etc.)"; - ot->exec = previews_clear_exec; - ot->invoke = WM_menu_invoke; + ot->exec = previews_clear_exec; + ot->invoke = WM_menu_invoke; - ot->prop = RNA_def_enum_flag(ot->srna, "id_type", preview_id_type_items, - FILTER_ID_SCE | FILTER_ID_OB | FILTER_ID_GR | - FILTER_ID_MA | FILTER_ID_LA | FILTER_ID_WO | FILTER_ID_TE | FILTER_ID_IM, - "Data-Block Type", "Which data-block previews to clear"); + ot->prop = RNA_def_enum_flag(ot->srna, + "id_type", + preview_id_type_items, + FILTER_ID_SCE | FILTER_ID_OB | FILTER_ID_GR | FILTER_ID_MA | + FILTER_ID_LA | FILTER_ID_WO | FILTER_ID_TE | FILTER_ID_IM, + "Data-Block Type", + "Which data-block previews to clear"); } /* *************************** Doc from UI ************* */ static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr_props; - char buf[512]; - short retval = OPERATOR_CANCELLED; + PointerRNA ptr_props; + char buf[512]; + short retval = OPERATOR_CANCELLED; - if (UI_but_online_manual_id_from_active(C, buf, sizeof(buf))) { - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); - RNA_string_set(&ptr_props, "doc_id", buf); + if (UI_but_online_manual_id_from_active(C, buf, sizeof(buf))) { + WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); + RNA_string_set(&ptr_props, "doc_id", buf); - retval = WM_operator_name_call_ptr( - C, WM_operatortype_find("WM_OT_doc_view_manual", false), - WM_OP_EXEC_DEFAULT, &ptr_props); + retval = WM_operator_name_call_ptr( + C, WM_operatortype_find("WM_OT_doc_view_manual", false), WM_OP_EXEC_DEFAULT, &ptr_props); - WM_operator_properties_free(&ptr_props); - } + WM_operator_properties_free(&ptr_props); + } - return retval; + return retval; } static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Online Manual"; - ot->idname = "WM_OT_doc_view_manual_ui_context"; - ot->description = "View a context based online manual in a web browser"; + /* identifiers */ + ot->name = "View Online Manual"; + ot->idname = "WM_OT_doc_view_manual_ui_context"; + ot->description = "View a context based online manual in a web browser"; - /* callbacks */ - ot->poll = ED_operator_regionactive; - ot->exec = doc_view_manual_ui_context_exec; + /* callbacks */ + ot->poll = ED_operator_regionactive; + ot->exec = doc_view_manual_ui_context_exec; } /* ******************************************************* */ /* toggle 3D for current window, turning it fullscreen if needed */ static void WM_OT_stereo3d_set(wmOperatorType *ot) { - PropertyRNA *prop; - - ot->name = "Set Stereo 3D"; - ot->idname = "WM_OT_set_stereo_3d"; - ot->description = "Toggle 3D stereo support for current window (or change the display mode)"; - - ot->exec = wm_stereo3d_set_exec; - ot->invoke = wm_stereo3d_set_invoke; - ot->poll = WM_operator_winactive; - ot->ui = wm_stereo3d_set_draw; - ot->check = wm_stereo3d_set_check; - ot->cancel = wm_stereo3d_set_cancel; - - prop = RNA_def_enum(ot->srna, "display_mode", rna_enum_stereo3d_display_items, S3D_DISPLAY_ANAGLYPH, "Display Mode", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "anaglyph_type", rna_enum_stereo3d_anaglyph_type_items, S3D_ANAGLYPH_REDCYAN, "Anaglyph Type", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "interlace_type", rna_enum_stereo3d_interlace_type_items, S3D_INTERLACE_ROW, "Interlace Type", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_interlace_swap", false, "Swap Left/Right", - "Swap left and right stereo channels"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_sidebyside_crosseyed", false, "Cross-Eyed", - "Right eye should see left image and vice-versa"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + ot->name = "Set Stereo 3D"; + ot->idname = "WM_OT_set_stereo_3d"; + ot->description = "Toggle 3D stereo support for current window (or change the display mode)"; + + ot->exec = wm_stereo3d_set_exec; + ot->invoke = wm_stereo3d_set_invoke; + ot->poll = WM_operator_winactive; + ot->ui = wm_stereo3d_set_draw; + ot->check = wm_stereo3d_set_check; + ot->cancel = wm_stereo3d_set_cancel; + + prop = RNA_def_enum(ot->srna, + "display_mode", + rna_enum_stereo3d_display_items, + S3D_DISPLAY_ANAGLYPH, + "Display Mode", + ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, + "anaglyph_type", + rna_enum_stereo3d_anaglyph_type_items, + S3D_ANAGLYPH_REDCYAN, + "Anaglyph Type", + ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, + "interlace_type", + rna_enum_stereo3d_interlace_type_items, + S3D_INTERLACE_ROW, + "Interlace Type", + ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, + "use_interlace_swap", + false, + "Swap Left/Right", + "Swap left and right stereo channels"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, + "use_sidebyside_crosseyed", + false, + "Cross-Eyed", + "Right eye should see left image and vice-versa"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } void wm_operatortypes_register(void) { - WM_operatortype_append(WM_OT_window_close); - WM_operatortype_append(WM_OT_window_new); - WM_operatortype_append(WM_OT_window_new_main); - WM_operatortype_append(WM_OT_read_history); - WM_operatortype_append(WM_OT_read_homefile); - WM_operatortype_append(WM_OT_read_factory_settings); - WM_operatortype_append(WM_OT_save_homefile); - WM_operatortype_append(WM_OT_save_userpref); - WM_operatortype_append(WM_OT_userpref_autoexec_path_add); - WM_operatortype_append(WM_OT_userpref_autoexec_path_remove); - WM_operatortype_append(WM_OT_window_fullscreen_toggle); - WM_operatortype_append(WM_OT_quit_blender); - WM_operatortype_append(WM_OT_open_mainfile); - WM_operatortype_append(WM_OT_revert_mainfile); - WM_operatortype_append(WM_OT_link); - WM_operatortype_append(WM_OT_append); - WM_operatortype_append(WM_OT_lib_relocate); - WM_operatortype_append(WM_OT_lib_reload); - WM_operatortype_append(WM_OT_recover_last_session); - WM_operatortype_append(WM_OT_recover_auto_save); - WM_operatortype_append(WM_OT_save_as_mainfile); - WM_operatortype_append(WM_OT_save_mainfile); - WM_operatortype_append(WM_OT_redraw_timer); - WM_operatortype_append(WM_OT_memory_statistics); - WM_operatortype_append(WM_OT_debug_menu); - WM_operatortype_append(WM_OT_operator_defaults); - 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_call_menu_pie); - WM_operatortype_append(WM_OT_call_panel); - WM_operatortype_append(WM_OT_radial_control); - WM_operatortype_append(WM_OT_stereo3d_set); + WM_operatortype_append(WM_OT_window_close); + WM_operatortype_append(WM_OT_window_new); + WM_operatortype_append(WM_OT_window_new_main); + WM_operatortype_append(WM_OT_read_history); + WM_operatortype_append(WM_OT_read_homefile); + WM_operatortype_append(WM_OT_read_factory_settings); + WM_operatortype_append(WM_OT_save_homefile); + WM_operatortype_append(WM_OT_save_userpref); + WM_operatortype_append(WM_OT_userpref_autoexec_path_add); + WM_operatortype_append(WM_OT_userpref_autoexec_path_remove); + WM_operatortype_append(WM_OT_window_fullscreen_toggle); + WM_operatortype_append(WM_OT_quit_blender); + WM_operatortype_append(WM_OT_open_mainfile); + WM_operatortype_append(WM_OT_revert_mainfile); + WM_operatortype_append(WM_OT_link); + WM_operatortype_append(WM_OT_append); + WM_operatortype_append(WM_OT_lib_relocate); + WM_operatortype_append(WM_OT_lib_reload); + WM_operatortype_append(WM_OT_recover_last_session); + WM_operatortype_append(WM_OT_recover_auto_save); + WM_operatortype_append(WM_OT_save_as_mainfile); + WM_operatortype_append(WM_OT_save_mainfile); + WM_operatortype_append(WM_OT_redraw_timer); + WM_operatortype_append(WM_OT_memory_statistics); + WM_operatortype_append(WM_OT_debug_menu); + WM_operatortype_append(WM_OT_operator_defaults); + 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_call_menu_pie); + WM_operatortype_append(WM_OT_call_panel); + WM_operatortype_append(WM_OT_radial_control); + WM_operatortype_append(WM_OT_stereo3d_set); #if defined(WIN32) - WM_operatortype_append(WM_OT_console_toggle); + WM_operatortype_append(WM_OT_console_toggle); #endif - WM_operatortype_append(WM_OT_previews_ensure); - WM_operatortype_append(WM_OT_previews_clear); - WM_operatortype_append(WM_OT_doc_view_manual_ui_context); + WM_operatortype_append(WM_OT_previews_ensure); + WM_operatortype_append(WM_OT_previews_clear); + WM_operatortype_append(WM_OT_doc_view_manual_ui_context); - /* gizmos */ - WM_operatortype_append(GIZMOGROUP_OT_gizmo_select); - WM_operatortype_append(GIZMOGROUP_OT_gizmo_tweak); + /* gizmos */ + WM_operatortype_append(GIZMOGROUP_OT_gizmo_select); + WM_operatortype_append(GIZMOGROUP_OT_gizmo_tweak); } /* circleselect-like modal operators */ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {GESTURE_MODAL_CIRCLE_ADD, "ADD", 0, "Add", ""}, - {GESTURE_MODAL_CIRCLE_SUB, "SUBTRACT", 0, "Subtract", ""}, - {GESTURE_MODAL_CIRCLE_SIZE, "SIZE", 0, "Size", ""}, + static const EnumPropertyItem modal_items[] = { + {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + {GESTURE_MODAL_CIRCLE_ADD, "ADD", 0, "Add", ""}, + {GESTURE_MODAL_CIRCLE_SUB, "SUBTRACT", 0, "Subtract", ""}, + {GESTURE_MODAL_CIRCLE_SIZE, "SIZE", 0, "Size", ""}, - {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, - {GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""}, - {GESTURE_MODAL_NOP, "NOP", 0, "No Operation", ""}, + {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, + {GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""}, + {GESTURE_MODAL_NOP, "NOP", 0, "No Operation", ""}, - {0, NULL, 0, NULL, NULL}, - }; + {0, NULL, 0, NULL, NULL}, + }; - /* WARNING - name is incorrect, use for non-3d views */ - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Gesture Circle"); + /* WARNING - name is incorrect, use for non-3d views */ + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Gesture Circle"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "View3D Gesture Circle", modal_items); + keymap = WM_modalkeymap_add(keyconf, "View3D Gesture Circle", modal_items); - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle"); - WM_modalkeymap_assign(keymap, "UV_OT_select_circle"); - WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle"); - WM_modalkeymap_assign(keymap, "MASK_OT_select_circle"); - WM_modalkeymap_assign(keymap, "NODE_OT_select_circle"); - WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_circle"); - WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle"); - WM_modalkeymap_assign(keymap, "ACTION_OT_select_circle"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle"); + WM_modalkeymap_assign(keymap, "UV_OT_select_circle"); + WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle"); + WM_modalkeymap_assign(keymap, "MASK_OT_select_circle"); + WM_modalkeymap_assign(keymap, "NODE_OT_select_circle"); + WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_circle"); + WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle"); + WM_modalkeymap_assign(keymap, "ACTION_OT_select_circle"); } /* straight line modal operators */ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, - {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem modal_items[] = { + {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, + {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Straight Line"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Straight Line"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "Gesture Straight Line", modal_items); + keymap = WM_modalkeymap_add(keyconf, "Gesture Straight Line", modal_items); - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line"); - WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient"); - WM_modalkeymap_assign(keymap, "MESH_OT_bisect"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line"); + WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient"); + WM_modalkeymap_assign(keymap, "MESH_OT_bisect"); } - /* box_select-like modal operators */ static void gesture_box_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, - {GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""}, - {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, - {0, NULL, 0, NULL, NULL}, - }; - - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Box"); - - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } - - keymap = WM_modalkeymap_add(keyconf, "Gesture Box", modal_items); - - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "ACTION_OT_select_box"); - WM_modalkeymap_assign(keymap, "ANIM_OT_channels_select_box"); - WM_modalkeymap_assign(keymap, "ANIM_OT_previewrange_set"); - WM_modalkeymap_assign(keymap, "INFO_OT_select_box"); - WM_modalkeymap_assign(keymap, "FILE_OT_select_box"); - WM_modalkeymap_assign(keymap, "GRAPH_OT_select_box"); - WM_modalkeymap_assign(keymap, "MARKER_OT_select_box"); - WM_modalkeymap_assign(keymap, "NLA_OT_select_box"); - WM_modalkeymap_assign(keymap, "NODE_OT_select_box"); - WM_modalkeymap_assign(keymap, "NODE_OT_viewer_border"); - WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show"); - WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_box"); -// WM_modalkeymap_assign(keymap, "SCREEN_OT_box_select"); // template - WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_box"); - WM_modalkeymap_assign(keymap, "SEQUENCER_OT_view_ghost_border"); - WM_modalkeymap_assign(keymap, "UV_OT_select_box"); - WM_modalkeymap_assign(keymap, "CLIP_OT_select_box"); - WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_box"); - WM_modalkeymap_assign(keymap, "MASK_OT_select_box"); - WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); - WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border"); - WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border"); - WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_box"); - WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border"); /* XXX TODO: zoom border should perhaps map rightmouse to zoom out instead of in+cancel */ - WM_modalkeymap_assign(keymap, "IMAGE_OT_render_border"); - WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border"); - WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_box"); + static const EnumPropertyItem modal_items[] = { + {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, + {GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""}, + {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Box"); + + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } + + keymap = WM_modalkeymap_add(keyconf, "Gesture Box", modal_items); + + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "ACTION_OT_select_box"); + WM_modalkeymap_assign(keymap, "ANIM_OT_channels_select_box"); + WM_modalkeymap_assign(keymap, "ANIM_OT_previewrange_set"); + WM_modalkeymap_assign(keymap, "INFO_OT_select_box"); + WM_modalkeymap_assign(keymap, "FILE_OT_select_box"); + WM_modalkeymap_assign(keymap, "GRAPH_OT_select_box"); + WM_modalkeymap_assign(keymap, "MARKER_OT_select_box"); + WM_modalkeymap_assign(keymap, "NLA_OT_select_box"); + WM_modalkeymap_assign(keymap, "NODE_OT_select_box"); + WM_modalkeymap_assign(keymap, "NODE_OT_viewer_border"); + WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show"); + WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_box"); + // WM_modalkeymap_assign(keymap, "SCREEN_OT_box_select"); // template + WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_box"); + WM_modalkeymap_assign(keymap, "SEQUENCER_OT_view_ghost_border"); + WM_modalkeymap_assign(keymap, "UV_OT_select_box"); + WM_modalkeymap_assign(keymap, "CLIP_OT_select_box"); + WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_box"); + WM_modalkeymap_assign(keymap, "MASK_OT_select_box"); + WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); + WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border"); + WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border"); + WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_box"); + WM_modalkeymap_assign( + keymap, + "VIEW3D_OT_zoom_border"); /* XXX TODO: zoom border should perhaps map rightmouse to zoom out instead of in+cancel */ + WM_modalkeymap_assign(keymap, "IMAGE_OT_render_border"); + WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border"); + WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_box"); } /* zoom to border modal operators */ static void gesture_zoom_border_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {GESTURE_MODAL_IN, "IN", 0, "In", ""}, - {GESTURE_MODAL_OUT, "OUT", 0, "Out", ""}, - {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem modal_items[] = { + {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + {GESTURE_MODAL_IN, "IN", 0, "In", ""}, + {GESTURE_MODAL_OUT, "OUT", 0, "Out", ""}, + {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Zoom Border"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Zoom Border"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "Gesture Zoom Border", modal_items); + keymap = WM_modalkeymap_add(keyconf, "Gesture Zoom Border", modal_items); - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); - WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border"); - WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); + WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border"); + WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border"); } /* default keymap for windows and screens, only call once per WM */ void wm_window_keymap(wmKeyConfig *keyconf) { - WM_keymap_ensure(keyconf, "Window", 0, 0); + WM_keymap_ensure(keyconf, "Window", 0, 0); - wm_gizmos_keymap(keyconf); - gesture_circle_modal_keymap(keyconf); - gesture_box_modal_keymap(keyconf); - gesture_zoom_border_modal_keymap(keyconf); - gesture_straightline_modal_keymap(keyconf); + wm_gizmos_keymap(keyconf); + gesture_circle_modal_keymap(keyconf); + gesture_box_modal_keymap(keyconf); + gesture_zoom_border_modal_keymap(keyconf); + gesture_straightline_modal_keymap(keyconf); - WM_keymap_fix_linking(); + WM_keymap_fix_linking(); } /** @@ -3414,96 +3678,150 @@ void wm_window_keymap(wmKeyConfig *keyconf) */ static bool rna_id_enum_filter_single(ID *id, void *user_data) { - return (id != user_data); + return (id != user_data); } /* Generic itemf's for operators that take library args */ -static const EnumPropertyItem *rna_id_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), - bool *r_free, ID *id, bool local, - bool (*filter_ids)(ID *id, void *user_data), void *user_data) -{ - EnumPropertyItem item_tmp = {0}, *item = NULL; - int totitem = 0; - int i = 0; - - for (; id; id = id->next) { - if ((filter_ids != NULL) && filter_ids(user_data, id) == false) { - i++; - continue; - } - if (local == false || !ID_IS_LINKED(id)) { - item_tmp.identifier = item_tmp.name = id->name + 2; - item_tmp.value = i++; - RNA_enum_item_add(&item, &totitem, &item_tmp); - } - } - - RNA_enum_item_end(&item, &totitem); - *r_free = true; - - return item; +static const EnumPropertyItem *rna_id_itemf(bContext *UNUSED(C), + PointerRNA *UNUSED(ptr), + bool *r_free, + ID *id, + bool local, + bool (*filter_ids)(ID *id, void *user_data), + void *user_data) +{ + EnumPropertyItem item_tmp = {0}, *item = NULL; + int totitem = 0; + int i = 0; + + for (; id; id = id->next) { + if ((filter_ids != NULL) && filter_ids(user_data, id) == false) { + i++; + continue; + } + if (local == false || !ID_IS_LINKED(id)) { + item_tmp.identifier = item_tmp.name = id->name + 2; + item_tmp.value = i++; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; } /* can add more as needed */ -const EnumPropertyItem *RNA_action_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_action_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->actions.first : NULL, false, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->actions.first : NULL, false, NULL, NULL); } #if 0 /* UNUSED */ const EnumPropertyItem *RNA_action_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->action.first : NULL, true); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->action.first : NULL, true); } #endif -const EnumPropertyItem *RNA_collection_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_collection_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->collections.first : NULL, false, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->collections.first : NULL, false, NULL, NULL); } -const EnumPropertyItem *RNA_collection_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_collection_local_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->collections.first : NULL, true, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->collections.first : NULL, true, NULL, NULL); } -const EnumPropertyItem *RNA_image_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_image_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->images.first : NULL, false, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->images.first : NULL, false, NULL, NULL); } -const EnumPropertyItem *RNA_image_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_image_local_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->images.first : NULL, true, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->images.first : NULL, true, NULL, NULL); } -const EnumPropertyItem *RNA_scene_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_scene_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scenes.first : NULL, false, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scenes.first : NULL, false, NULL, NULL); } -const EnumPropertyItem *RNA_scene_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_scene_local_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scenes.first : NULL, true, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scenes.first : NULL, true, NULL, NULL); } -const EnumPropertyItem *RNA_scene_without_active_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_scene_without_active_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - Scene *scene_active = C ? CTX_data_scene(C) : NULL; - return rna_id_itemf( - C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scenes.first : NULL, true, - rna_id_enum_filter_single, scene_active); + Scene *scene_active = C ? CTX_data_scene(C) : NULL; + return rna_id_itemf(C, + ptr, + r_free, + C ? (ID *)CTX_data_main(C)->scenes.first : NULL, + true, + rna_id_enum_filter_single, + scene_active); } -const EnumPropertyItem *RNA_movieclip_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_movieclip_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : NULL, false, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : NULL, false, NULL, NULL); } -const EnumPropertyItem *RNA_movieclip_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_movieclip_local_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : NULL, true, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : NULL, true, NULL, NULL); } -const EnumPropertyItem *RNA_mask_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_mask_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->masks.first : NULL, false, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->masks.first : NULL, false, NULL, NULL); } -const EnumPropertyItem *RNA_mask_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *RNA_mask_local_itemf(bContext *C, + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->masks.first : NULL, true, NULL, NULL); + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->masks.first : NULL, true, NULL, NULL); } diff --git a/source/blender/windowmanager/intern/wm_panel_type.c b/source/blender/windowmanager/intern/wm_panel_type.c index f00129c139b..4324ae03b2c 100644 --- a/source/blender/windowmanager/intern/wm_panel_type.c +++ b/source/blender/windowmanager/intern/wm_panel_type.c @@ -41,46 +41,46 @@ static GHash *g_paneltypes_hash = NULL; PanelType *WM_paneltype_find(const char *idname, bool quiet) { - PanelType *pt; + PanelType *pt; - if (idname[0]) { - pt = BLI_ghash_lookup(g_paneltypes_hash, idname); - if (pt) { - return pt; - } - } + if (idname[0]) { + pt = BLI_ghash_lookup(g_paneltypes_hash, idname); + if (pt) { + return pt; + } + } - if (!quiet) { - printf("search for unknown paneltype %s\n", idname); - } + if (!quiet) { + printf("search for unknown paneltype %s\n", idname); + } - return NULL; + return NULL; } bool WM_paneltype_add(PanelType *pt) { - BLI_ghash_insert(g_paneltypes_hash, pt->idname, pt); - return true; + BLI_ghash_insert(g_paneltypes_hash, pt->idname, pt); + return true; } void WM_paneltype_remove(PanelType *pt) { - bool ok; + bool ok; - ok = BLI_ghash_remove(g_paneltypes_hash, pt->idname, NULL, NULL); + ok = BLI_ghash_remove(g_paneltypes_hash, pt->idname, NULL, NULL); - BLI_assert(ok); - (void)ok; + BLI_assert(ok); + (void)ok; } /* called on initialize WM_init() */ void WM_paneltype_init(void) { - /* reserve size is set based on blender default setup */ - g_paneltypes_hash = BLI_ghash_str_new_ex("g_paneltypes_hash gh", 512); + /* reserve size is set based on blender default setup */ + g_paneltypes_hash = BLI_ghash_str_new_ex("g_paneltypes_hash gh", 512); } void WM_paneltype_clear(void) { - BLI_ghash_free(g_paneltypes_hash, NULL, NULL); + BLI_ghash_free(g_paneltypes_hash, NULL, NULL); } diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 12931c2f5ac..098284de0d1 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -71,7 +71,7 @@ #include "DEG_depsgraph.h" -#include "WM_api.h" /* only for WM_main_playanim */ +#include "WM_api.h" /* only for WM_main_playanim */ #ifdef WITH_AUDASPACE # include <AUD_Device.h> @@ -96,146 +96,146 @@ static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset); typedef struct PlayState { - /* window and viewport size */ - int win_x, win_y; + /* window and viewport size */ + int win_x, win_y; - /* current zoom level */ - float zoom; + /* current zoom level */ + float zoom; - /* playback state */ - short direction; - short next_frame; + /* playback state */ + short direction; + short next_frame; - bool once; - bool turbo; - bool pingpong; - bool noskip; - bool indicator; - bool sstep; - bool wait2; - bool stopped; - bool go; - /* waiting for images to load */ - bool loading; - /* x/y image flip */ - bool draw_flip[2]; + bool once; + bool turbo; + bool pingpong; + bool noskip; + bool indicator; + bool sstep; + bool wait2; + bool stopped; + bool go; + /* waiting for images to load */ + bool loading; + /* x/y image flip */ + bool draw_flip[2]; - int fstep; + int fstep; - /* current picture */ - struct PlayAnimPict *picture; + /* current picture */ + struct PlayAnimPict *picture; - /* set once at the start */ - int ibufx, ibufy; - int fontid; + /* set once at the start */ + int ibufx, ibufy; + int fontid; - /* saves passing args */ - struct ImBuf *curframe_ibuf; + /* saves passing args */ + struct ImBuf *curframe_ibuf; - /* restarts player for file drop */ - char dropped_file[FILE_MAX]; + /* restarts player for file drop */ + char dropped_file[FILE_MAX]; - bool need_frame_update; - int frame_cursor_x; + bool need_frame_update; + int frame_cursor_x; } PlayState; /* for debugging */ #if 0 void print_ps(PlayState *ps) { - printf("ps:\n"); - printf(" direction=%d,\n", (int)ps->direction); - printf(" next=%d,\n", ps->next); - printf(" once=%d,\n", ps->once); - printf(" turbo=%d,\n", ps->turbo); - printf(" pingpong=%d,\n", ps->pingpong); - printf(" noskip=%d,\n", ps->noskip); - printf(" sstep=%d,\n", ps->sstep); - printf(" pause=%d,\n", ps->pause); - printf(" wait2=%d,\n", ps->wait2); - printf(" stopped=%d,\n", ps->stopped); - printf(" go=%d,\n\n", ps->go); - fflush(stdout); + printf("ps:\n"); + printf(" direction=%d,\n", (int)ps->direction); + printf(" next=%d,\n", ps->next); + printf(" once=%d,\n", ps->once); + printf(" turbo=%d,\n", ps->turbo); + printf(" pingpong=%d,\n", ps->pingpong); + printf(" noskip=%d,\n", ps->noskip); + printf(" sstep=%d,\n", ps->sstep); + printf(" pause=%d,\n", ps->pause); + printf(" wait2=%d,\n", ps->wait2); + printf(" stopped=%d,\n", ps->stopped); + printf(" go=%d,\n\n", ps->go); + fflush(stdout); } #endif /* global for window and events */ typedef enum eWS_Qual { - WS_QUAL_LSHIFT = (1 << 0), - WS_QUAL_RSHIFT = (1 << 1), - WS_QUAL_SHIFT = (WS_QUAL_LSHIFT | WS_QUAL_RSHIFT), - WS_QUAL_LALT = (1 << 2), - WS_QUAL_RALT = (1 << 3), - WS_QUAL_ALT = (WS_QUAL_LALT | WS_QUAL_RALT), - WS_QUAL_LCTRL = (1 << 4), - WS_QUAL_RCTRL = (1 << 5), - WS_QUAL_CTRL = (WS_QUAL_LCTRL | WS_QUAL_RCTRL), - WS_QUAL_LMOUSE = (1 << 16), - WS_QUAL_MMOUSE = (1 << 17), - WS_QUAL_RMOUSE = (1 << 18), - WS_QUAL_MOUSE = (WS_QUAL_LMOUSE | WS_QUAL_MMOUSE | WS_QUAL_RMOUSE), + WS_QUAL_LSHIFT = (1 << 0), + WS_QUAL_RSHIFT = (1 << 1), + WS_QUAL_SHIFT = (WS_QUAL_LSHIFT | WS_QUAL_RSHIFT), + WS_QUAL_LALT = (1 << 2), + WS_QUAL_RALT = (1 << 3), + WS_QUAL_ALT = (WS_QUAL_LALT | WS_QUAL_RALT), + WS_QUAL_LCTRL = (1 << 4), + WS_QUAL_RCTRL = (1 << 5), + WS_QUAL_CTRL = (WS_QUAL_LCTRL | WS_QUAL_RCTRL), + WS_QUAL_LMOUSE = (1 << 16), + WS_QUAL_MMOUSE = (1 << 17), + WS_QUAL_RMOUSE = (1 << 18), + WS_QUAL_MOUSE = (WS_QUAL_LMOUSE | WS_QUAL_MMOUSE | WS_QUAL_RMOUSE), } eWS_Qual; static struct WindowStateGlobal { - GHOST_SystemHandle ghost_system; - void *ghost_window; - GPUContext *gpu_context; + GHOST_SystemHandle ghost_system; + void *ghost_window; + GPUContext *gpu_context; - /* events */ - eWS_Qual qual; + /* events */ + eWS_Qual qual; } g_WS = {NULL}; static void playanim_window_get_size(int *r_width, int *r_height) { - GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window); - *r_width = GHOST_GetWidthRectangle(bounds); - *r_height = GHOST_GetHeightRectangle(bounds); - GHOST_DisposeRectangle(bounds); + GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window); + *r_width = GHOST_GetWidthRectangle(bounds); + *r_height = GHOST_GetHeightRectangle(bounds); + GHOST_DisposeRectangle(bounds); } static void playanim_gl_matrix(void) { - /* unified matrix, note it affects offset for drawing */ - /* note! cannot use GPU_matrix_ortho_2d_set here because shader ignores. */ - GPU_matrix_ortho_set(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f); + /* unified matrix, note it affects offset for drawing */ + /* note! cannot use GPU_matrix_ortho_2d_set here because shader ignores. */ + GPU_matrix_ortho_set(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f); } /* implementation */ static void playanim_event_qual_update(void) { - int val; + int val; - /* Shift */ - GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftShift, &val); - SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LSHIFT); + /* Shift */ + GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftShift, &val); + SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LSHIFT); - GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightShift, &val); - SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RSHIFT); + GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightShift, &val); + SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RSHIFT); - /* Control */ - GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftControl, &val); - SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LCTRL); + /* Control */ + GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftControl, &val); + SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LCTRL); - GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightControl, &val); - SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RCTRL); + GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightControl, &val); + SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RCTRL); - /* Alt */ - GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftAlt, &val); - SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LALT); + /* Alt */ + GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftAlt, &val); + SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LALT); - GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightAlt, &val); - SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RALT); + GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightAlt, &val); + SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RALT); } typedef struct PlayAnimPict { - struct PlayAnimPict *next, *prev; - uchar *mem; - int size; - const char *name; - struct ImBuf *ibuf; - struct anim *anim; - int frame; - int IB_flags; + struct PlayAnimPict *next, *prev; + uchar *mem; + int size; + const char *name; + struct ImBuf *ibuf; + struct anim *anim; + int frame; + int IB_flags; } PlayAnimPict; static struct ListBase picsbase = {NULL, NULL}; @@ -253,1410 +253,1406 @@ static int added_images = 0; static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step) { - if (step > 0) { - while (step-- && playanim) { - playanim = playanim->next; - } - } - else if (step < 0) { - while (step++ && playanim) { - playanim = playanim->prev; - } - } - return playanim; + if (step > 0) { + while (step-- && playanim) { + playanim = playanim->next; + } + } + else if (step < 0) { + while (step++ && playanim) { + playanim = playanim->prev; + } + } + return playanim; } static int pupdate_time(void) { - static double ltime; - double time; + static double ltime; + double time; - time = PIL_check_seconds_timer(); + time = PIL_check_seconds_timer(); - ptottime += (time - ltime); - ltime = time; - return (ptottime < 0); + ptottime += (time - ltime); + ltime = time; + return (ptottime < 0); } -static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep) +static void playanim_toscreen( + PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep) { - float offs_x, offs_y; - float span_x, span_y; - - if (ibuf == NULL) { - printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>"); - return; - } - if (ibuf->rect == NULL && ibuf->rect_float) { - IMB_rect_from_float(ibuf); - imb_freerectfloatImBuf(ibuf); - } - if (ibuf->rect == NULL) { - return; - } - - GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); - - /* size within window */ - span_x = (ps->zoom * ibuf->x) / (float)ps->win_x; - span_y = (ps->zoom * ibuf->y) / (float)ps->win_y; - - /* offset within window */ - offs_x = 0.5f * (1.0f - span_x); - offs_y = 0.5f * (1.0f - span_y); - - CLAMP(offs_x, 0.0f, 1.0f); - CLAMP(offs_y, 0.0f, 1.0f); - - glClearColor(0.1, 0.1, 0.1, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - /* checkerboard for case alpha */ - if (ibuf->planes == 32) { - GPU_blend(true); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - imm_draw_box_checker_2d(offs_x, offs_y, offs_x + span_x, offs_y + span_y); - } - - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); - - immDrawPixelsTex( - &state, - offs_x + (ps->draw_flip[0] ? span_x : 0.0f), - offs_y + (ps->draw_flip[1] ? span_y : 0.0f), - ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, - ibuf->rect, - ((ps->draw_flip[0] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_x), - ((ps->draw_flip[1] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_y), - NULL); - - GPU_blend(false); - - pupdate_time(); - - if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) { - int sizex, sizey; - float fsizex_inv, fsizey_inv; - char str[32 + FILE_MAX]; - BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime); - - playanim_window_get_size(&sizex, &sizey); - fsizex_inv = 1.0f / sizex; - fsizey_inv = 1.0f / sizey; - - BLF_color4f(fontid, 1.0, 1.0, 1.0, 1.0); - BLF_enable(fontid, BLF_ASPECT); - BLF_aspect(fontid, fsizex_inv, fsizey_inv, 1.0f); - BLF_position(fontid, 10.0f * fsizex_inv, 10.0f * fsizey_inv, 0.0f); - BLF_draw(fontid, str, sizeof(str)); - } - - if (ps->indicator) { - float fac = ps->picture->frame / (double)(((PlayAnimPict *)picsbase.last)->frame - ((PlayAnimPict *)picsbase.first)->frame); - - fac = 2.0f * fac - 1.0f; - GPU_matrix_push_projection(); - GPU_matrix_identity_projection_set(); - GPU_matrix_push(); - GPU_matrix_identity_set(); - - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor3ub(0, 255, 0); - - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, fac, -1.0f); - immVertex2f(pos, fac, 1.0f); - immEnd(); - - immUnbindProgram(); - - GPU_matrix_pop(); - GPU_matrix_pop_projection(); - } - - GHOST_SwapWindowBuffers(g_WS.ghost_window); + float offs_x, offs_y; + float span_x, span_y; + + if (ibuf == NULL) { + printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>"); + return; + } + if (ibuf->rect == NULL && ibuf->rect_float) { + IMB_rect_from_float(ibuf); + imb_freerectfloatImBuf(ibuf); + } + if (ibuf->rect == NULL) { + return; + } + + GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); + + /* size within window */ + span_x = (ps->zoom * ibuf->x) / (float)ps->win_x; + span_y = (ps->zoom * ibuf->y) / (float)ps->win_y; + + /* offset within window */ + offs_x = 0.5f * (1.0f - span_x); + offs_y = 0.5f * (1.0f - span_y); + + CLAMP(offs_x, 0.0f, 1.0f); + CLAMP(offs_y, 0.0f, 1.0f); + + glClearColor(0.1, 0.1, 0.1, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + /* checkerboard for case alpha */ + if (ibuf->planes == 32) { + GPU_blend(true); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + imm_draw_box_checker_2d(offs_x, offs_y, offs_x + span_x, offs_y + span_y); + } + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + + immDrawPixelsTex(&state, + offs_x + (ps->draw_flip[0] ? span_x : 0.0f), + offs_y + (ps->draw_flip[1] ? span_y : 0.0f), + ibuf->x, + ibuf->y, + GL_RGBA, + GL_UNSIGNED_BYTE, + GL_NEAREST, + ibuf->rect, + ((ps->draw_flip[0] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_x), + ((ps->draw_flip[1] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_y), + NULL); + + GPU_blend(false); + + pupdate_time(); + + if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) { + int sizex, sizey; + float fsizex_inv, fsizey_inv; + char str[32 + FILE_MAX]; + BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime); + + playanim_window_get_size(&sizex, &sizey); + fsizex_inv = 1.0f / sizex; + fsizey_inv = 1.0f / sizey; + + BLF_color4f(fontid, 1.0, 1.0, 1.0, 1.0); + BLF_enable(fontid, BLF_ASPECT); + BLF_aspect(fontid, fsizex_inv, fsizey_inv, 1.0f); + BLF_position(fontid, 10.0f * fsizex_inv, 10.0f * fsizey_inv, 0.0f); + BLF_draw(fontid, str, sizeof(str)); + } + + if (ps->indicator) { + float fac = ps->picture->frame / (double)(((PlayAnimPict *)picsbase.last)->frame - + ((PlayAnimPict *)picsbase.first)->frame); + + fac = 2.0f * fac - 1.0f; + GPU_matrix_push_projection(); + GPU_matrix_identity_projection_set(); + GPU_matrix_push(); + GPU_matrix_identity_set(); + + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ub(0, 255, 0); + + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, fac, -1.0f); + immVertex2f(pos, fac, 1.0f); + immEnd(); + + immUnbindProgram(); + + GPU_matrix_pop(); + GPU_matrix_pop_projection(); + } + + GHOST_SwapWindowBuffers(g_WS.ghost_window); } -static void build_pict_list_ex(PlayState *ps, const char *first, int totframes, int fstep, int fontid) +static void build_pict_list_ex( + PlayState *ps, const char *first, int totframes, int fstep, int fontid) { - char filepath[FILE_MAX]; - uchar *mem; -// short val; - PlayAnimPict *picture = NULL; - struct ImBuf *ibuf = NULL; - struct anim *anim; - - if (IMB_isanim(first)) { - /* OCIO_TODO: support different input color space */ - anim = IMB_open_anim(first, IB_rect, 0, NULL); - if (anim) { - int pic; - ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); - if (ibuf) { - playanim_toscreen(ps, NULL, ibuf, fontid, fstep); - IMB_freeImBuf(ibuf); - } - - for (pic = 0; pic < IMB_anim_get_duration(anim, IMB_TC_NONE); pic++) { - picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "Pict"); - picture->anim = anim; - picture->frame = pic; - picture->IB_flags = IB_rect; - picture->name = BLI_sprintfN("%s : %4.d", first, pic + 1); - BLI_addtail(&picsbase, picture); - } - } - else { - printf("couldn't open anim %s\n", first); - } - } - else { - int count = 0; - - int fp_framenr; - struct { - char head[FILE_MAX], tail[FILE_MAX]; - unsigned short digits; - } fp_decoded; - - BLI_strncpy(filepath, first, sizeof(filepath)); - fp_framenr = BLI_stringdec(filepath, fp_decoded.head, fp_decoded.tail, &fp_decoded.digits); - - pupdate_time(); - ptottime = 1.0; - - /* O_DIRECT - * - * If set, all reads and writes on the resulting file descriptor will - * be performed directly to or from the user program buffer, provided - * appropriate size and alignment restrictions are met. Refer to the - * F_SETFL and F_DIOINFO commands in the fcntl(2) manual entry for - * information about how to determine the alignment constraints. - * O_DIRECT is a Silicon Graphics extension and is only supported on - * local EFS and XFS file systems. - */ - - while (IMB_ispic(filepath) && totframes) { - bool hasevent; - size_t size; - int file; - - file = BLI_open(filepath, O_BINARY | O_RDONLY, 0); - if (file < 0) { - /* print errno? */ - return; - } - - picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture"); - if (picture == NULL) { - printf("Not enough memory for pict struct '%s'\n", filepath); - close(file); - return; - } - size = BLI_file_descriptor_size(file); - - if (size < 1) { - close(file); - MEM_freeN(picture); - return; - } - - picture->size = size; - picture->IB_flags = IB_rect; - - if (fromdisk == false) { - mem = MEM_mallocN(size, "build pic list"); - if (mem == NULL) { - printf("Couldn't get memory\n"); - close(file); - MEM_freeN(picture); - return; - } - - if (read(file, mem, size) != size) { - printf("Error while reading %s\n", filepath); - close(file); - MEM_freeN(picture); - MEM_freeN(mem); - return; - } - } - else { - mem = NULL; - } - - picture->mem = mem; - picture->name = BLI_strdup(filepath); - picture->frame = count; - close(file); - BLI_addtail(&picsbase, picture); - count++; - - pupdate_time(); - - if (ptottime > 1.0) { - /* OCIO_TODO: support different input color space */ - if (picture->mem) { - ibuf = IMB_ibImageFromMemory(picture->mem, picture->size, - picture->IB_flags, NULL, picture->name); - } - else { - ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL); - } - if (ibuf) { - playanim_toscreen(ps, picture, ibuf, fontid, fstep); - IMB_freeImBuf(ibuf); - } - pupdate_time(); - ptottime = 0.0; - } - - /* create a new filepath each time */ - fp_framenr += fstep; - BLI_stringenc(filepath, fp_decoded.head, fp_decoded.tail, fp_decoded.digits, fp_framenr); - - while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0))) { - if (hasevent) { - GHOST_DispatchEvents(g_WS.ghost_system); - } - if (ps->loading == false) { - return; - } - } - - totframes--; - } - } - return; + char filepath[FILE_MAX]; + uchar *mem; + // short val; + PlayAnimPict *picture = NULL; + struct ImBuf *ibuf = NULL; + struct anim *anim; + + if (IMB_isanim(first)) { + /* OCIO_TODO: support different input color space */ + anim = IMB_open_anim(first, IB_rect, 0, NULL); + if (anim) { + int pic; + ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); + if (ibuf) { + playanim_toscreen(ps, NULL, ibuf, fontid, fstep); + IMB_freeImBuf(ibuf); + } + + for (pic = 0; pic < IMB_anim_get_duration(anim, IMB_TC_NONE); pic++) { + picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "Pict"); + picture->anim = anim; + picture->frame = pic; + picture->IB_flags = IB_rect; + picture->name = BLI_sprintfN("%s : %4.d", first, pic + 1); + BLI_addtail(&picsbase, picture); + } + } + else { + printf("couldn't open anim %s\n", first); + } + } + else { + int count = 0; + + int fp_framenr; + struct { + char head[FILE_MAX], tail[FILE_MAX]; + unsigned short digits; + } fp_decoded; + + BLI_strncpy(filepath, first, sizeof(filepath)); + fp_framenr = BLI_stringdec(filepath, fp_decoded.head, fp_decoded.tail, &fp_decoded.digits); + + pupdate_time(); + ptottime = 1.0; + + /* O_DIRECT + * + * If set, all reads and writes on the resulting file descriptor will + * be performed directly to or from the user program buffer, provided + * appropriate size and alignment restrictions are met. Refer to the + * F_SETFL and F_DIOINFO commands in the fcntl(2) manual entry for + * information about how to determine the alignment constraints. + * O_DIRECT is a Silicon Graphics extension and is only supported on + * local EFS and XFS file systems. + */ + + while (IMB_ispic(filepath) && totframes) { + bool hasevent; + size_t size; + int file; + + file = BLI_open(filepath, O_BINARY | O_RDONLY, 0); + if (file < 0) { + /* print errno? */ + return; + } + + picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture"); + if (picture == NULL) { + printf("Not enough memory for pict struct '%s'\n", filepath); + close(file); + return; + } + size = BLI_file_descriptor_size(file); + + if (size < 1) { + close(file); + MEM_freeN(picture); + return; + } + + picture->size = size; + picture->IB_flags = IB_rect; + + if (fromdisk == false) { + mem = MEM_mallocN(size, "build pic list"); + if (mem == NULL) { + printf("Couldn't get memory\n"); + close(file); + MEM_freeN(picture); + return; + } + + if (read(file, mem, size) != size) { + printf("Error while reading %s\n", filepath); + close(file); + MEM_freeN(picture); + MEM_freeN(mem); + return; + } + } + else { + mem = NULL; + } + + picture->mem = mem; + picture->name = BLI_strdup(filepath); + picture->frame = count; + close(file); + BLI_addtail(&picsbase, picture); + count++; + + pupdate_time(); + + if (ptottime > 1.0) { + /* OCIO_TODO: support different input color space */ + if (picture->mem) { + ibuf = IMB_ibImageFromMemory( + picture->mem, picture->size, picture->IB_flags, NULL, picture->name); + } + else { + ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL); + } + if (ibuf) { + playanim_toscreen(ps, picture, ibuf, fontid, fstep); + IMB_freeImBuf(ibuf); + } + pupdate_time(); + ptottime = 0.0; + } + + /* create a new filepath each time */ + fp_framenr += fstep; + BLI_stringenc(filepath, fp_decoded.head, fp_decoded.tail, fp_decoded.digits, fp_framenr); + + while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0))) { + if (hasevent) { + GHOST_DispatchEvents(g_WS.ghost_system); + } + if (ps->loading == false) { + return; + } + } + + totframes--; + } + } + return; } static void build_pict_list(PlayState *ps, const char *first, int totframes, int fstep, int fontid) { - ps->loading = true; - build_pict_list_ex(ps, first, totframes, fstep, fontid); - ps->loading = false; + ps->loading = true; + build_pict_list_ex(ps, first, totframes, fstep, fontid); + ps->loading = false; } static void update_sound_fps(void) { #ifdef WITH_AUDASPACE - if (playback_handle) { - /* swaptime stores the 1.0/fps ratio */ - double speed = 1.0 / (swaptime * fps_movie); + if (playback_handle) { + /* swaptime stores the 1.0/fps ratio */ + double speed = 1.0 / (swaptime * fps_movie); - AUD_Handle_setPitch(playback_handle, speed); - } + AUD_Handle_setPitch(playback_handle, speed); + } #endif } static void tag_change_frame(PlayState *ps, int cx) { - ps->need_frame_update = true; - ps->frame_cursor_x = cx; + ps->need_frame_update = true; + ps->frame_cursor_x = cx; } static void change_frame(PlayState *ps) { - if (!ps->need_frame_update) { - return; - } + if (!ps->need_frame_update) { + return; + } - int sizex, sizey; - int i, i_last; + int sizex, sizey; + int i, i_last; - if (BLI_listbase_is_empty(&picsbase)) { - return; - } + if (BLI_listbase_is_empty(&picsbase)) { + return; + } - playanim_window_get_size(&sizex, &sizey); - i_last = ((struct PlayAnimPict *)picsbase.last)->frame; - i = (i_last * ps->frame_cursor_x) / sizex; - CLAMP(i, 0, i_last); + playanim_window_get_size(&sizex, &sizey); + i_last = ((struct PlayAnimPict *)picsbase.last)->frame; + i = (i_last * ps->frame_cursor_x) / sizex; + CLAMP(i, 0, i_last); #ifdef WITH_AUDASPACE - if (scrub_handle) { - AUD_Handle_stop(scrub_handle); - scrub_handle = NULL; - } - - if (playback_handle) { - AUD_Status status = AUD_Handle_getStatus(playback_handle); - if (status != AUD_STATUS_PLAYING) { - AUD_Handle_stop(playback_handle); - playback_handle = AUD_Device_play(audio_device, source, 1); - if (playback_handle) { - AUD_Handle_setPosition(playback_handle, i / fps_movie); - scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie); - } - update_sound_fps(); - } - else { - AUD_Handle_setPosition(playback_handle, i / fps_movie); - scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie); - } - } - else if (source) { - playback_handle = AUD_Device_play(audio_device, source, 1); - if (playback_handle) { - AUD_Handle_setPosition(playback_handle, i / fps_movie); - scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie); - } - update_sound_fps(); - } + if (scrub_handle) { + AUD_Handle_stop(scrub_handle); + scrub_handle = NULL; + } + + if (playback_handle) { + AUD_Status status = AUD_Handle_getStatus(playback_handle); + if (status != AUD_STATUS_PLAYING) { + AUD_Handle_stop(playback_handle); + playback_handle = AUD_Device_play(audio_device, source, 1); + if (playback_handle) { + AUD_Handle_setPosition(playback_handle, i / fps_movie); + scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie); + } + update_sound_fps(); + } + else { + AUD_Handle_setPosition(playback_handle, i / fps_movie); + scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie); + } + } + else if (source) { + playback_handle = AUD_Device_play(audio_device, source, 1); + if (playback_handle) { + AUD_Handle_setPosition(playback_handle, i / fps_movie); + scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie); + } + update_sound_fps(); + } #endif - ps->picture = BLI_findlink(&picsbase, i); - BLI_assert(ps->picture != NULL); + ps->picture = BLI_findlink(&picsbase, i); + BLI_assert(ps->picture != NULL); - ps->sstep = true; - ps->wait2 = false; - ps->next_frame = 0; + ps->sstep = true; + ps->wait2 = false; + ps->next_frame = 0; - ps->need_frame_update = false; + ps->need_frame_update = false; } static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) { - PlayState *ps = (PlayState *)ps_void; - GHOST_TEventType type = GHOST_GetEventType(evt); - int val; - - // print_ps(ps); - - playanim_event_qual_update(); - - /* convert ghost event into value keyboard or mouse */ - val = ELEM(type, GHOST_kEventKeyDown, GHOST_kEventButtonDown); - - /* first check if we're busy loading files */ - if (ps->loading) { - switch (type) { - case GHOST_kEventKeyDown: - case GHOST_kEventKeyUp: - { - GHOST_TEventKeyData *key_data; - - key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt); - switch (key_data->key) { - case GHOST_kKeyEsc: - ps->loading = false; - break; - default: - break; - } - break; - } - default: - break; - } - return 1; - } - - - if (ps->wait2 && ps->stopped) { - ps->stopped = false; - } - - if (ps->wait2) { - pupdate_time(); - ptottime = 0; - } - - switch (type) { - case GHOST_kEventKeyDown: - case GHOST_kEventKeyUp: - { - GHOST_TEventKeyData *key_data; - - key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt); - switch (key_data->key) { - case GHOST_kKeyA: - if (val) { - ps->noskip = !ps->noskip; - } - break; - case GHOST_kKeyI: - if (val) { - ps->indicator = !ps->indicator; - } - break; - case GHOST_kKeyP: - if (val) { - ps->pingpong = !ps->pingpong; - } - break; - case GHOST_kKeyF: - { - if (val) { - int axis = (g_WS.qual & WS_QUAL_SHIFT) ? 1 : 0; - ps->draw_flip[axis] = !ps->draw_flip[axis]; - } - break; - } - case GHOST_kKey1: - case GHOST_kKeyNumpad1: - if (val) { - swaptime = ps->fstep / 60.0; - update_sound_fps(); - } - break; - case GHOST_kKey2: - case GHOST_kKeyNumpad2: - if (val) { - swaptime = ps->fstep / 50.0; - update_sound_fps(); - } - break; - case GHOST_kKey3: - case GHOST_kKeyNumpad3: - if (val) { - swaptime = ps->fstep / 30.0; - update_sound_fps(); - } - break; - case GHOST_kKey4: - case GHOST_kKeyNumpad4: - if (g_WS.qual & WS_QUAL_SHIFT) { - swaptime = ps->fstep / 24.0; - update_sound_fps(); - } - else { - swaptime = ps->fstep / 25.0; - update_sound_fps(); - } - break; - case GHOST_kKey5: - case GHOST_kKeyNumpad5: - if (val) { - swaptime = ps->fstep / 20.0; - update_sound_fps(); - } - break; - case GHOST_kKey6: - case GHOST_kKeyNumpad6: - if (val) { - swaptime = ps->fstep / 15.0; - update_sound_fps(); - } - break; - case GHOST_kKey7: - case GHOST_kKeyNumpad7: - if (val) { - swaptime = ps->fstep / 12.0; - update_sound_fps(); - } - break; - case GHOST_kKey8: - case GHOST_kKeyNumpad8: - if (val) { - swaptime = ps->fstep / 10.0; - update_sound_fps(); - } - break; - case GHOST_kKey9: - case GHOST_kKeyNumpad9: - if (val) { - swaptime = ps->fstep / 6.0; - update_sound_fps(); - } - break; - case GHOST_kKeyLeftArrow: - if (val) { - ps->sstep = true; - ps->wait2 = false; - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->picture = picsbase.first; - ps->next_frame = 0; - } - else { - ps->next_frame = -1; - } - } - break; - case GHOST_kKeyDownArrow: - if (val) { - ps->wait2 = false; - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->next_frame = ps->direction = -1; - } - else { - ps->next_frame = -10; - ps->sstep = true; - } - } - break; - case GHOST_kKeyRightArrow: - if (val) { - ps->sstep = true; - ps->wait2 = false; - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->picture = picsbase.last; - ps->next_frame = 0; - } - else { - ps->next_frame = 1; - } - } - break; - case GHOST_kKeyUpArrow: - if (val) { - ps->wait2 = false; - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->next_frame = ps->direction = 1; - } - else { - ps->next_frame = 10; - ps->sstep = true; - } - } - break; - - case GHOST_kKeySlash: - case GHOST_kKeyNumpadSlash: - if (val) { - if (g_WS.qual & WS_QUAL_SHIFT) { - if (ps->curframe_ibuf) { - printf(" Name: %s | Speed: %.2f frames/s\n", - ps->curframe_ibuf->name, ps->fstep / swaptime); - } - } - else { - swaptime = ps->fstep / 5.0; - update_sound_fps(); - } - } - break; - case GHOST_kKey0: - case GHOST_kKeyNumpad0: - if (val) { - if (ps->once) { - ps->once = ps->wait2 = false; - } - else { - ps->picture = NULL; - ps->once = true; - ps->wait2 = false; - } - } - break; - - case GHOST_kKeySpace: - if (val) { - if (ps->wait2 || ps->sstep) { - ps->wait2 = ps->sstep = false; + PlayState *ps = (PlayState *)ps_void; + GHOST_TEventType type = GHOST_GetEventType(evt); + int val; + + // print_ps(ps); + + playanim_event_qual_update(); + + /* convert ghost event into value keyboard or mouse */ + val = ELEM(type, GHOST_kEventKeyDown, GHOST_kEventButtonDown); + + /* first check if we're busy loading files */ + if (ps->loading) { + switch (type) { + case GHOST_kEventKeyDown: + case GHOST_kEventKeyUp: { + GHOST_TEventKeyData *key_data; + + key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt); + switch (key_data->key) { + case GHOST_kKeyEsc: + ps->loading = false; + break; + default: + break; + } + break; + } + default: + break; + } + return 1; + } + + if (ps->wait2 && ps->stopped) { + ps->stopped = false; + } + + if (ps->wait2) { + pupdate_time(); + ptottime = 0; + } + + switch (type) { + case GHOST_kEventKeyDown: + case GHOST_kEventKeyUp: { + GHOST_TEventKeyData *key_data; + + key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt); + switch (key_data->key) { + case GHOST_kKeyA: + if (val) { + ps->noskip = !ps->noskip; + } + break; + case GHOST_kKeyI: + if (val) { + ps->indicator = !ps->indicator; + } + break; + case GHOST_kKeyP: + if (val) { + ps->pingpong = !ps->pingpong; + } + break; + case GHOST_kKeyF: { + if (val) { + int axis = (g_WS.qual & WS_QUAL_SHIFT) ? 1 : 0; + ps->draw_flip[axis] = !ps->draw_flip[axis]; + } + break; + } + case GHOST_kKey1: + case GHOST_kKeyNumpad1: + if (val) { + swaptime = ps->fstep / 60.0; + update_sound_fps(); + } + break; + case GHOST_kKey2: + case GHOST_kKeyNumpad2: + if (val) { + swaptime = ps->fstep / 50.0; + update_sound_fps(); + } + break; + case GHOST_kKey3: + case GHOST_kKeyNumpad3: + if (val) { + swaptime = ps->fstep / 30.0; + update_sound_fps(); + } + break; + case GHOST_kKey4: + case GHOST_kKeyNumpad4: + if (g_WS.qual & WS_QUAL_SHIFT) { + swaptime = ps->fstep / 24.0; + update_sound_fps(); + } + else { + swaptime = ps->fstep / 25.0; + update_sound_fps(); + } + break; + case GHOST_kKey5: + case GHOST_kKeyNumpad5: + if (val) { + swaptime = ps->fstep / 20.0; + update_sound_fps(); + } + break; + case GHOST_kKey6: + case GHOST_kKeyNumpad6: + if (val) { + swaptime = ps->fstep / 15.0; + update_sound_fps(); + } + break; + case GHOST_kKey7: + case GHOST_kKeyNumpad7: + if (val) { + swaptime = ps->fstep / 12.0; + update_sound_fps(); + } + break; + case GHOST_kKey8: + case GHOST_kKeyNumpad8: + if (val) { + swaptime = ps->fstep / 10.0; + update_sound_fps(); + } + break; + case GHOST_kKey9: + case GHOST_kKeyNumpad9: + if (val) { + swaptime = ps->fstep / 6.0; + update_sound_fps(); + } + break; + case GHOST_kKeyLeftArrow: + if (val) { + ps->sstep = true; + ps->wait2 = false; + if (g_WS.qual & WS_QUAL_SHIFT) { + ps->picture = picsbase.first; + ps->next_frame = 0; + } + else { + ps->next_frame = -1; + } + } + break; + case GHOST_kKeyDownArrow: + if (val) { + ps->wait2 = false; + if (g_WS.qual & WS_QUAL_SHIFT) { + ps->next_frame = ps->direction = -1; + } + else { + ps->next_frame = -10; + ps->sstep = true; + } + } + break; + case GHOST_kKeyRightArrow: + if (val) { + ps->sstep = true; + ps->wait2 = false; + if (g_WS.qual & WS_QUAL_SHIFT) { + ps->picture = picsbase.last; + ps->next_frame = 0; + } + else { + ps->next_frame = 1; + } + } + break; + case GHOST_kKeyUpArrow: + if (val) { + ps->wait2 = false; + if (g_WS.qual & WS_QUAL_SHIFT) { + ps->next_frame = ps->direction = 1; + } + else { + ps->next_frame = 10; + ps->sstep = true; + } + } + break; + + case GHOST_kKeySlash: + case GHOST_kKeyNumpadSlash: + if (val) { + if (g_WS.qual & WS_QUAL_SHIFT) { + if (ps->curframe_ibuf) { + printf(" Name: %s | Speed: %.2f frames/s\n", + ps->curframe_ibuf->name, + ps->fstep / swaptime); + } + } + else { + swaptime = ps->fstep / 5.0; + update_sound_fps(); + } + } + break; + case GHOST_kKey0: + case GHOST_kKeyNumpad0: + if (val) { + if (ps->once) { + ps->once = ps->wait2 = false; + } + else { + ps->picture = NULL; + ps->once = true; + ps->wait2 = false; + } + } + break; + + case GHOST_kKeySpace: + if (val) { + if (ps->wait2 || ps->sstep) { + ps->wait2 = ps->sstep = false; #ifdef WITH_AUDASPACE - { - PlayAnimPict *picture = picsbase.first; - /* TODO - store in ps direct? */ - int i = 0; - - while (picture && picture != ps->picture) { - i++; - picture = picture->next; - } - if (playback_handle) { - AUD_Handle_stop(playback_handle); - } - playback_handle = AUD_Device_play(audio_device, source, 1); - if (playback_handle) { - AUD_Handle_setPosition(playback_handle, i / fps_movie); - } - update_sound_fps(); - } + { + PlayAnimPict *picture = picsbase.first; + /* TODO - store in ps direct? */ + int i = 0; + + while (picture && picture != ps->picture) { + i++; + picture = picture->next; + } + if (playback_handle) { + AUD_Handle_stop(playback_handle); + } + playback_handle = AUD_Device_play(audio_device, source, 1); + if (playback_handle) { + AUD_Handle_setPosition(playback_handle, i / fps_movie); + } + update_sound_fps(); + } #endif - } - else { - ps->sstep = true; - ps->wait2 = true; + } + else { + ps->sstep = true; + ps->wait2 = true; #ifdef WITH_AUDASPACE - if (playback_handle) { - AUD_Handle_stop(playback_handle); - playback_handle = NULL; - } + if (playback_handle) { + AUD_Handle_stop(playback_handle); + playback_handle = NULL; + } #endif - } - } - break; - case GHOST_kKeyEnter: - case GHOST_kKeyNumpadEnter: - if (val) { - ps->wait2 = ps->sstep = false; + } + } + break; + case GHOST_kKeyEnter: + case GHOST_kKeyNumpadEnter: + if (val) { + ps->wait2 = ps->sstep = false; #ifdef WITH_AUDASPACE - { - PlayAnimPict *picture = picsbase.first; - /* TODO - store in ps direct? */ - int i = 0; - while (picture && picture != ps->picture) { - i++; - picture = picture->next; - } - if (playback_handle) { - AUD_Handle_stop(playback_handle); - } - playback_handle = AUD_Device_play(audio_device, source, 1); - if (playback_handle) { - AUD_Handle_setPosition(playback_handle, i / fps_movie); - } - update_sound_fps(); - } + { + PlayAnimPict *picture = picsbase.first; + /* TODO - store in ps direct? */ + int i = 0; + while (picture && picture != ps->picture) { + i++; + picture = picture->next; + } + if (playback_handle) { + AUD_Handle_stop(playback_handle); + } + playback_handle = AUD_Device_play(audio_device, source, 1); + if (playback_handle) { + AUD_Handle_setPosition(playback_handle, i / fps_movie); + } + update_sound_fps(); + } #endif - } - break; - case GHOST_kKeyPeriod: - case GHOST_kKeyNumpadPeriod: - if (val) { - if (ps->sstep) { - ps->wait2 = false; - } - else { - ps->sstep = true; - ps->wait2 = !ps->wait2; + } + break; + case GHOST_kKeyPeriod: + case GHOST_kKeyNumpadPeriod: + if (val) { + if (ps->sstep) { + ps->wait2 = false; + } + else { + ps->sstep = true; + ps->wait2 = !ps->wait2; #ifdef WITH_AUDASPACE - if (playback_handle) { - AUD_Handle_stop(playback_handle); - playback_handle = NULL; - } + if (playback_handle) { + AUD_Handle_stop(playback_handle); + playback_handle = NULL; + } #endif - } - } - break; - case GHOST_kKeyEqual: - case GHOST_kKeyPlus: - case GHOST_kKeyNumpadPlus: - { - if (val == 0) { - break; - } - if (g_WS.qual & WS_QUAL_CTRL) { - playanim_window_zoom(ps, 0.1f); - } - else { - if (swaptime > ps->fstep / 60.0) { - swaptime /= 1.1; - update_sound_fps(); - } - } - break; - } - case GHOST_kKeyMinus: - case GHOST_kKeyNumpadMinus: - { - if (val == 0) { - break; - } - if (g_WS.qual & WS_QUAL_CTRL) { - playanim_window_zoom(ps, -0.1f); - } - else { - if (swaptime < ps->fstep / 5.0) { - swaptime *= 1.1; - update_sound_fps(); - } - } - break; - } - case GHOST_kKeyEsc: - ps->go = false; - break; - default: - break; - } - break; - } - case GHOST_kEventButtonDown: - case GHOST_kEventButtonUp: - { - GHOST_TEventButtonData *bd = GHOST_GetEventData(evt); - int cx, cy, sizex, sizey, inside_window; - - GHOST_GetCursorPosition(g_WS.ghost_system, &cx, &cy); - GHOST_ScreenToClient(g_WS.ghost_window, cx, cy, &cx, &cy); - playanim_window_get_size(&sizex, &sizey); - - inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey); - - if (bd->button == GHOST_kButtonMaskLeft) { - if (type == GHOST_kEventButtonDown) { - if (inside_window) { - g_WS.qual |= WS_QUAL_LMOUSE; - tag_change_frame(ps, cx); - } - } - else { - g_WS.qual &= ~WS_QUAL_LMOUSE; - } - } - else if (bd->button == GHOST_kButtonMaskMiddle) { - if (type == GHOST_kEventButtonDown) { - if (inside_window) { - g_WS.qual |= WS_QUAL_MMOUSE; - } - } - else { - g_WS.qual &= ~WS_QUAL_MMOUSE; - } - } - else if (bd->button == GHOST_kButtonMaskRight) { - if (type == GHOST_kEventButtonDown) { - if (inside_window) { - g_WS.qual |= WS_QUAL_RMOUSE; - } - } - else { - g_WS.qual &= ~WS_QUAL_RMOUSE; - } - } - break; - } - case GHOST_kEventCursorMove: - { - if (g_WS.qual & WS_QUAL_LMOUSE) { - GHOST_TEventCursorData *cd = GHOST_GetEventData(evt); - int cx, cy; - - /* Ignore 'in-between' events, since they can make scrubbing lag. - * - * Ideally we would keep into the event queue and see if this is the last motion event. - * however the API currently doesn't support this. */ - { - int x_test, y_test; - GHOST_GetCursorPosition(g_WS.ghost_system, &x_test, &y_test); - if (x_test != cd->x || y_test != cd->y) { - /* we're not the last event... skipping */ - break; - } - } - - GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy); - - tag_change_frame(ps, cx); - } - break; - } - case GHOST_kEventWindowActivate: - case GHOST_kEventWindowDeactivate: - { - g_WS.qual &= ~WS_QUAL_MOUSE; - break; - } - case GHOST_kEventWindowSize: - case GHOST_kEventWindowMove: - { - float zoomx, zoomy; - - playanim_window_get_size(&ps->win_x, &ps->win_y); - GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); - - zoomx = (float) ps->win_x / ps->ibufx; - zoomy = (float) ps->win_y / ps->ibufy; - - /* zoom always show entire image */ - ps->zoom = MIN2(zoomx, zoomy); - - glViewport(0, 0, ps->win_x, ps->win_y); - glScissor(0, 0, ps->win_x, ps->win_y); - - playanim_gl_matrix(); - - ptottime = 0.0; - playanim_toscreen(ps, ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep); - - break; - } - case GHOST_kEventQuit: - case GHOST_kEventWindowClose: - { - ps->go = false; - break; - } - case GHOST_kEventDraggingDropDone: - { - GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); - - if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { - GHOST_TStringArray *stra = ddd->data; - int a; - - for (a = 0; a < stra->count; a++) { - BLI_strncpy(ps->dropped_file, (char *)stra->strings[a], sizeof(ps->dropped_file)); - ps->go = false; - printf("drop file %s\n", stra->strings[a]); - break; /* only one drop element supported now */ - } - } - break; - } - default: - /* quiet warnings */ - break; - } - - return 1; + } + } + break; + case GHOST_kKeyEqual: + case GHOST_kKeyPlus: + case GHOST_kKeyNumpadPlus: { + if (val == 0) { + break; + } + if (g_WS.qual & WS_QUAL_CTRL) { + playanim_window_zoom(ps, 0.1f); + } + else { + if (swaptime > ps->fstep / 60.0) { + swaptime /= 1.1; + update_sound_fps(); + } + } + break; + } + case GHOST_kKeyMinus: + case GHOST_kKeyNumpadMinus: { + if (val == 0) { + break; + } + if (g_WS.qual & WS_QUAL_CTRL) { + playanim_window_zoom(ps, -0.1f); + } + else { + if (swaptime < ps->fstep / 5.0) { + swaptime *= 1.1; + update_sound_fps(); + } + } + break; + } + case GHOST_kKeyEsc: + ps->go = false; + break; + default: + break; + } + break; + } + case GHOST_kEventButtonDown: + case GHOST_kEventButtonUp: { + GHOST_TEventButtonData *bd = GHOST_GetEventData(evt); + int cx, cy, sizex, sizey, inside_window; + + GHOST_GetCursorPosition(g_WS.ghost_system, &cx, &cy); + GHOST_ScreenToClient(g_WS.ghost_window, cx, cy, &cx, &cy); + playanim_window_get_size(&sizex, &sizey); + + inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey); + + if (bd->button == GHOST_kButtonMaskLeft) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) { + g_WS.qual |= WS_QUAL_LMOUSE; + tag_change_frame(ps, cx); + } + } + else { + g_WS.qual &= ~WS_QUAL_LMOUSE; + } + } + else if (bd->button == GHOST_kButtonMaskMiddle) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) { + g_WS.qual |= WS_QUAL_MMOUSE; + } + } + else { + g_WS.qual &= ~WS_QUAL_MMOUSE; + } + } + else if (bd->button == GHOST_kButtonMaskRight) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) { + g_WS.qual |= WS_QUAL_RMOUSE; + } + } + else { + g_WS.qual &= ~WS_QUAL_RMOUSE; + } + } + break; + } + case GHOST_kEventCursorMove: { + if (g_WS.qual & WS_QUAL_LMOUSE) { + GHOST_TEventCursorData *cd = GHOST_GetEventData(evt); + int cx, cy; + + /* Ignore 'in-between' events, since they can make scrubbing lag. + * + * Ideally we would keep into the event queue and see if this is the last motion event. + * however the API currently doesn't support this. */ + { + int x_test, y_test; + GHOST_GetCursorPosition(g_WS.ghost_system, &x_test, &y_test); + if (x_test != cd->x || y_test != cd->y) { + /* we're not the last event... skipping */ + break; + } + } + + GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy); + + tag_change_frame(ps, cx); + } + break; + } + case GHOST_kEventWindowActivate: + case GHOST_kEventWindowDeactivate: { + g_WS.qual &= ~WS_QUAL_MOUSE; + break; + } + case GHOST_kEventWindowSize: + case GHOST_kEventWindowMove: { + float zoomx, zoomy; + + playanim_window_get_size(&ps->win_x, &ps->win_y); + GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); + + zoomx = (float)ps->win_x / ps->ibufx; + zoomy = (float)ps->win_y / ps->ibufy; + + /* zoom always show entire image */ + ps->zoom = MIN2(zoomx, zoomy); + + glViewport(0, 0, ps->win_x, ps->win_y); + glScissor(0, 0, ps->win_x, ps->win_y); + + playanim_gl_matrix(); + + ptottime = 0.0; + playanim_toscreen(ps, ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep); + + break; + } + case GHOST_kEventQuit: + case GHOST_kEventWindowClose: { + ps->go = false; + break; + } + case GHOST_kEventDraggingDropDone: { + GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); + + if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { + GHOST_TStringArray *stra = ddd->data; + int a; + + for (a = 0; a < stra->count; a++) { + BLI_strncpy(ps->dropped_file, (char *)stra->strings[a], sizeof(ps->dropped_file)); + ps->go = false; + printf("drop file %s\n", stra->strings[a]); + break; /* only one drop element supported now */ + } + } + break; + } + default: + /* quiet warnings */ + break; + } + + return 1; } static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey) { - GHOST_GLSettings glsettings = {0}; - GHOST_TUns32 scr_w, scr_h; - - GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h); - - posy = (scr_h - posy - sizey); - - g_WS.ghost_window = GHOST_CreateWindow(g_WS.ghost_system, - title, - posx, posy, sizex, sizey, - /* could optionally start fullscreen */ - GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, - glsettings); + GHOST_GLSettings glsettings = {0}; + GHOST_TUns32 scr_w, scr_h; + + GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h); + + posy = (scr_h - posy - sizey); + + g_WS.ghost_window = GHOST_CreateWindow(g_WS.ghost_system, + title, + posx, + posy, + sizex, + sizey, + /* could optionally start fullscreen */ + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, + glsettings); } static void playanim_window_zoom(PlayState *ps, const float zoom_offset) { - int sizex, sizey; - /* int ofsx, ofsy; */ /* UNUSED */ - - if (ps->zoom + zoom_offset > 0.0f) { - ps->zoom += zoom_offset; - } - - // playanim_window_get_position(&ofsx, &ofsy); - playanim_window_get_size(&sizex, &sizey); - /* ofsx += sizex / 2; */ /* UNUSED */ - /* ofsy += sizey / 2; */ /* UNUSED */ - sizex = ps->zoom * ps->ibufx; - sizey = ps->zoom * ps->ibufy; - /* ofsx -= sizex / 2; */ /* UNUSED */ - /* ofsy -= sizey / 2; */ /* UNUSED */ - // window_set_position(g_WS.ghost_window, sizex, sizey); - GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); + int sizex, sizey; + /* int ofsx, ofsy; */ /* UNUSED */ + + if (ps->zoom + zoom_offset > 0.0f) { + ps->zoom += zoom_offset; + } + + // playanim_window_get_position(&ofsx, &ofsy); + playanim_window_get_size(&sizex, &sizey); + /* ofsx += sizex / 2; */ /* UNUSED */ + /* ofsy += sizey / 2; */ /* UNUSED */ + sizex = ps->zoom * ps->ibufx; + sizey = ps->zoom * ps->ibufy; + /* ofsx -= sizex / 2; */ /* UNUSED */ + /* ofsy -= sizey / 2; */ /* UNUSED */ + // window_set_position(g_WS.ghost_window, sizex, sizey); + GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); } /* return path for restart */ static char *wm_main_playanim_intern(int argc, const char **argv) { - struct ImBuf *ibuf = NULL; - static char filepath[FILE_MAX]; /* abused to return dropped file path */ - GHOST_TUns32 maxwinx, maxwiny; - int i; - /* This was done to disambiguate the name for use under c++. */ - int start_x = 0, start_y = 0; - int sfra = -1; - int efra = -1; - int totblock; - - PlayState ps = {0}; - - /* ps.doubleb = true;*/ /* UNUSED */ - ps.go = true; - ps.direction = true; - ps.next_frame = 1; - ps.once = false; - ps.turbo = false; - ps.pingpong = false; - ps.noskip = false; - ps.sstep = false; - ps.wait2 = false; - ps.stopped = false; - ps.loading = false; - ps.picture = NULL; - ps.indicator = false; - ps.dropped_file[0] = 0; - ps.zoom = 1.0f; - /* resetmap = false */ - ps.draw_flip[0] = false; - ps.draw_flip[1] = false; - - ps.fstep = 1; - - ps.fontid = -1; - - while (argc > 1) { - if (argv[1][0] == '-') { - switch (argv[1][1]) { - case 'm': - fromdisk = true; - break; - case 'p': - if (argc > 3) { - start_x = atoi(argv[2]); - start_y = atoi(argv[3]); - argc -= 2; - argv += 2; - } - else { - printf("too few arguments for -p (need 2): skipping\n"); - } - break; - case 'f': - if (argc > 3) { - double fps = atof(argv[2]); - double fps_base = atof(argv[3]); - if (fps == 0.0) { - fps = 1; - printf("invalid fps," - "forcing 1\n"); - } - swaptime = fps_base / fps; - argc -= 2; - argv += 2; - } - else { - printf("too few arguments for -f (need 2): skipping\n"); - } - break; - case 's': - sfra = atoi(argv[2]); - CLAMP(sfra, 1, MAXFRAME); - argc--; - argv++; - break; - case 'e': - efra = atoi(argv[2]); - CLAMP(efra, 1, MAXFRAME); - argc--; - argv++; - break; - case 'j': - ps.fstep = atoi(argv[2]); - CLAMP(ps.fstep, 1, MAXFRAME); - swaptime *= ps.fstep; - argc--; - argv++; - break; - default: - printf("unknown option '%c': skipping\n", argv[1][1]); - break; - } - argc--; - argv++; - } - else { - break; - } - } - - if (argc > 1) { - BLI_strncpy(filepath, argv[1], sizeof(filepath)); - } - else { - printf("%s: no filepath argument given\n", __func__); - exit(1); - } - - if (IMB_isanim(filepath)) { - /* OCIO_TODO: support different input color spaces */ - struct anim *anim; - anim = IMB_open_anim(filepath, IB_rect, 0, NULL); - if (anim) { - ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); - IMB_close_anim(anim); - anim = NULL; - } - } - else if (!IMB_ispic(filepath)) { - printf("%s: '%s' not an image file\n", __func__, filepath); - exit(1); - } - - if (ibuf == NULL) { - /* OCIO_TODO: support different input color space */ - ibuf = IMB_loadiffname(filepath, IB_rect, NULL); - } - - if (ibuf == NULL) { - printf("%s: '%s' couldn't open\n", __func__, filepath); - exit(1); - } - - { - - GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps); - - g_WS.ghost_system = GHOST_CreateSystem(); - GHOST_AddEventConsumer(g_WS.ghost_system, consumer); - - playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y); - } - - GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny); - - //GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); - - /* initialize OpenGL immediate mode */ - g_WS.gpu_context = GPU_context_create(); - GPU_init(); - immActivate(); - - /* initialize the font */ - BLF_init(); - ps.fontid = BLF_load_mem("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); - BLF_size(ps.fontid, 11, 72); - - ps.ibufx = ibuf->x; - ps.ibufy = ibuf->y; - - ps.win_x = ps.ibufx; - ps.win_y = ps.ibufy; - - if (maxwinx % ibuf->x) { - maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x)); - } - if (maxwiny % ibuf->y) { - maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y)); - } - - - glClearColor(0.1, 0.1, 0.1, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - int win_x, win_y; - playanim_window_get_size(&win_x, &win_y); - glViewport(0, 0, win_x, win_y); - glScissor(0, 0, win_x, win_y); - playanim_gl_matrix(); - - GHOST_SwapWindowBuffers(g_WS.ghost_window); - - if (sfra == -1 || efra == -1) { - /* one of the frames was invalid, just use all images */ - sfra = 1; - efra = MAXFRAME; - } - - build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); + struct ImBuf *ibuf = NULL; + static char filepath[FILE_MAX]; /* abused to return dropped file path */ + GHOST_TUns32 maxwinx, maxwiny; + int i; + /* This was done to disambiguate the name for use under c++. */ + int start_x = 0, start_y = 0; + int sfra = -1; + int efra = -1; + int totblock; + + PlayState ps = {0}; + + /* ps.doubleb = true;*/ /* UNUSED */ + ps.go = true; + ps.direction = true; + ps.next_frame = 1; + ps.once = false; + ps.turbo = false; + ps.pingpong = false; + ps.noskip = false; + ps.sstep = false; + ps.wait2 = false; + ps.stopped = false; + ps.loading = false; + ps.picture = NULL; + ps.indicator = false; + ps.dropped_file[0] = 0; + ps.zoom = 1.0f; + /* resetmap = false */ + ps.draw_flip[0] = false; + ps.draw_flip[1] = false; + + ps.fstep = 1; + + ps.fontid = -1; + + while (argc > 1) { + if (argv[1][0] == '-') { + switch (argv[1][1]) { + case 'm': + fromdisk = true; + break; + case 'p': + if (argc > 3) { + start_x = atoi(argv[2]); + start_y = atoi(argv[3]); + argc -= 2; + argv += 2; + } + else { + printf("too few arguments for -p (need 2): skipping\n"); + } + break; + case 'f': + if (argc > 3) { + double fps = atof(argv[2]); + double fps_base = atof(argv[3]); + if (fps == 0.0) { + fps = 1; + printf( + "invalid fps," + "forcing 1\n"); + } + swaptime = fps_base / fps; + argc -= 2; + argv += 2; + } + else { + printf("too few arguments for -f (need 2): skipping\n"); + } + break; + case 's': + sfra = atoi(argv[2]); + CLAMP(sfra, 1, MAXFRAME); + argc--; + argv++; + break; + case 'e': + efra = atoi(argv[2]); + CLAMP(efra, 1, MAXFRAME); + argc--; + argv++; + break; + case 'j': + ps.fstep = atoi(argv[2]); + CLAMP(ps.fstep, 1, MAXFRAME); + swaptime *= ps.fstep; + argc--; + argv++; + break; + default: + printf("unknown option '%c': skipping\n", argv[1][1]); + break; + } + argc--; + argv++; + } + else { + break; + } + } + + if (argc > 1) { + BLI_strncpy(filepath, argv[1], sizeof(filepath)); + } + else { + printf("%s: no filepath argument given\n", __func__); + exit(1); + } + + if (IMB_isanim(filepath)) { + /* OCIO_TODO: support different input color spaces */ + struct anim *anim; + anim = IMB_open_anim(filepath, IB_rect, 0, NULL); + if (anim) { + ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); + IMB_close_anim(anim); + anim = NULL; + } + } + else if (!IMB_ispic(filepath)) { + printf("%s: '%s' not an image file\n", __func__, filepath); + exit(1); + } + + if (ibuf == NULL) { + /* OCIO_TODO: support different input color space */ + ibuf = IMB_loadiffname(filepath, IB_rect, NULL); + } + + if (ibuf == NULL) { + printf("%s: '%s' couldn't open\n", __func__, filepath); + exit(1); + } + + { + + GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps); + + g_WS.ghost_system = GHOST_CreateSystem(); + GHOST_AddEventConsumer(g_WS.ghost_system, consumer); + + playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y); + } + + GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny); + + //GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); + + /* initialize OpenGL immediate mode */ + g_WS.gpu_context = GPU_context_create(); + GPU_init(); + immActivate(); + + /* initialize the font */ + BLF_init(); + ps.fontid = BLF_load_mem( + "monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); + BLF_size(ps.fontid, 11, 72); + + ps.ibufx = ibuf->x; + ps.ibufy = ibuf->y; + + ps.win_x = ps.ibufx; + ps.win_y = ps.ibufy; + + if (maxwinx % ibuf->x) { + maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x)); + } + if (maxwiny % ibuf->y) { + maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y)); + } + + glClearColor(0.1, 0.1, 0.1, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + int win_x, win_y; + playanim_window_get_size(&win_x, &win_y); + glViewport(0, 0, win_x, win_y); + glScissor(0, 0, win_x, win_y); + playanim_gl_matrix(); + + GHOST_SwapWindowBuffers(g_WS.ghost_window); + + if (sfra == -1 || efra == -1) { + /* one of the frames was invalid, just use all images */ + sfra = 1; + efra = MAXFRAME; + } + + build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); #ifdef WITH_AUDASPACE - source = AUD_Sound_file(filepath); - { - struct anim *anim_movie = ((struct PlayAnimPict *)picsbase.first)->anim; - if (anim_movie) { - short frs_sec = 25; - float frs_sec_base = 1.0; - - IMB_anim_get_fps(anim_movie, &frs_sec, &frs_sec_base, true); - - fps_movie = (double) frs_sec / (double) frs_sec_base; - /* enforce same fps for movie as sound */ - swaptime = ps.fstep / fps_movie; - } - } + source = AUD_Sound_file(filepath); + { + struct anim *anim_movie = ((struct PlayAnimPict *)picsbase.first)->anim; + if (anim_movie) { + short frs_sec = 25; + float frs_sec_base = 1.0; + + IMB_anim_get_fps(anim_movie, &frs_sec, &frs_sec_base, true); + + fps_movie = (double)frs_sec / (double)frs_sec_base; + /* enforce same fps for movie as sound */ + swaptime = ps.fstep / fps_movie; + } + } #endif - for (i = 2; i < argc; i++) { - BLI_strncpy(filepath, argv[i], sizeof(filepath)); - build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); - } + for (i = 2; i < argc; i++) { + BLI_strncpy(filepath, argv[i], sizeof(filepath)); + build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); + } - IMB_freeImBuf(ibuf); - ibuf = NULL; + IMB_freeImBuf(ibuf); + ibuf = NULL; - pupdate_time(); - ptottime = 0; + pupdate_time(); + ptottime = 0; - /* newly added in 2.6x, without this images never get freed */ + /* newly added in 2.6x, without this images never get freed */ #define USE_IMB_CACHE - while (ps.go) { - if (ps.pingpong) { - ps.direction = -ps.direction; - } - - if (ps.direction == 1) { - ps.picture = picsbase.first; - } - else { - ps.picture = picsbase.last; - } - - if (ps.picture == NULL) { - printf("couldn't find pictures\n"); - ps.go = false; - } - if (ps.pingpong) { - if (ps.direction == 1) { - ps.picture = ps.picture->next; - } - else { - ps.picture = ps.picture->prev; - } - } - if (ptottime > 0.0) { - ptottime = 0.0; - } + while (ps.go) { + if (ps.pingpong) { + ps.direction = -ps.direction; + } + + if (ps.direction == 1) { + ps.picture = picsbase.first; + } + else { + ps.picture = picsbase.last; + } + + if (ps.picture == NULL) { + printf("couldn't find pictures\n"); + ps.go = false; + } + if (ps.pingpong) { + if (ps.direction == 1) { + ps.picture = ps.picture->next; + } + else { + ps.picture = ps.picture->prev; + } + } + if (ptottime > 0.0) { + ptottime = 0.0; + } #ifdef WITH_AUDASPACE - if (playback_handle) { - AUD_Handle_stop(playback_handle); - } - playback_handle = AUD_Device_play(audio_device, source, 1); - update_sound_fps(); + if (playback_handle) { + AUD_Handle_stop(playback_handle); + } + playback_handle = AUD_Device_play(audio_device, source, 1); + update_sound_fps(); #endif - while (ps.picture) { - int hasevent; + while (ps.picture) { + int hasevent; #ifndef USE_IMB_CACHE - if (ibuf != NULL && ibuf->ftype == 0) { - IMB_freeImBuf(ibuf); - } + if (ibuf != NULL && ibuf->ftype == 0) { + IMB_freeImBuf(ibuf); + } #endif - if (ps.picture->ibuf) { - ibuf = ps.picture->ibuf; - } - else if (ps.picture->anim) { - ibuf = IMB_anim_absolute(ps.picture->anim, ps.picture->frame, IMB_TC_NONE, IMB_PROXY_NONE); - } - else if (ps.picture->mem) { - /* use correct colorspace here */ - ibuf = IMB_ibImageFromMemory(ps.picture->mem, ps.picture->size, - ps.picture->IB_flags, NULL, ps.picture->name); - } - else { - /* use correct colorspace here */ - ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags, NULL); - } - - if (ibuf) { + if (ps.picture->ibuf) { + ibuf = ps.picture->ibuf; + } + else if (ps.picture->anim) { + ibuf = IMB_anim_absolute(ps.picture->anim, ps.picture->frame, IMB_TC_NONE, IMB_PROXY_NONE); + } + else if (ps.picture->mem) { + /* use correct colorspace here */ + ibuf = IMB_ibImageFromMemory( + ps.picture->mem, ps.picture->size, ps.picture->IB_flags, NULL, ps.picture->name); + } + else { + /* use correct colorspace here */ + ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags, NULL); + } + + if (ibuf) { #ifdef USE_FRAME_CACHE_LIMIT - LinkData *node; + LinkData *node; #endif #ifdef USE_IMB_CACHE - ps.picture->ibuf = ibuf; + ps.picture->ibuf = ibuf; #endif #ifdef USE_FRAME_CACHE_LIMIT - /* really basic memory conservation scheme. Keep frames in a fifo queue */ - node = inmempicsbase.last; - - while (node && added_images > PLAY_FRAME_CACHE_MAX) { - PlayAnimPict *pic = node->data; - - if (pic->ibuf && pic->ibuf != ibuf) { - LinkData *node_tmp; - IMB_freeImBuf(pic->ibuf); - pic->ibuf = NULL; - node_tmp = node->prev; - BLI_freelinkN(&inmempicsbase, node); - added_images--; - node = node_tmp; - } - else { - node = node->prev; - } - } - - BLI_addhead(&inmempicsbase, BLI_genericNodeN(ps.picture)); - added_images++; -#endif /* USE_FRAME_CACHE_LIMIT */ - - BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name)); - - /* why only windows? (from 2.4x) - campbell */ + /* really basic memory conservation scheme. Keep frames in a fifo queue */ + node = inmempicsbase.last; + + while (node && added_images > PLAY_FRAME_CACHE_MAX) { + PlayAnimPict *pic = node->data; + + if (pic->ibuf && pic->ibuf != ibuf) { + LinkData *node_tmp; + IMB_freeImBuf(pic->ibuf); + pic->ibuf = NULL; + node_tmp = node->prev; + BLI_freelinkN(&inmempicsbase, node); + added_images--; + node = node_tmp; + } + else { + node = node->prev; + } + } + + BLI_addhead(&inmempicsbase, BLI_genericNodeN(ps.picture)); + added_images++; +#endif /* USE_FRAME_CACHE_LIMIT */ + + BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name)); + + /* why only windows? (from 2.4x) - campbell */ #ifdef _WIN32 - GHOST_SetTitle(g_WS.ghost_window, ps.picture->name); + GHOST_SetTitle(g_WS.ghost_window, ps.picture->name); #endif - while (pupdate_time()) { - PIL_sleep_ms(1); - } - ptottime -= swaptime; - playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep); - } /* else delete */ - else { - printf("error: can't play this image type\n"); - exit(0); - } - - if (ps.once) { - if (ps.picture->next == NULL) { - ps.wait2 = true; - } - else if (ps.picture->prev == NULL) { - ps.wait2 = true; - } - } - - ps.next_frame = ps.direction; - - while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0))) { - GHOST_DispatchEvents(g_WS.ghost_system); - } - if (ps.go == false) { - break; - } - change_frame(&ps); - if (!hasevent) { - PIL_sleep_ms(1); - } - if (ps.wait2) { - continue; - } - - ps.wait2 = ps.sstep; - - if (ps.wait2 == false && ps.stopped == false) { - ps.stopped = true; - } - - pupdate_time(); - - if (ps.picture && ps.next_frame) { - /* always at least set one step */ - while (ps.picture) { - ps.picture = playanim_step(ps.picture, ps.next_frame); - - if (ps.once && ps.picture != NULL) { - if (ps.picture->next == NULL) { - ps.wait2 = true; - } - else if (ps.picture->prev == NULL) { - ps.wait2 = true; - } - } - - if (ps.wait2 || ptottime < swaptime || ps.turbo || ps.noskip) { - break; - } - ptottime -= swaptime; - } - if (ps.picture == NULL && ps.sstep) { - ps.picture = playanim_step(ps.picture, ps.next_frame); - } - } - if (ps.go == false) { - break; - } - } - } - while ((ps.picture = BLI_pophead(&picsbase))) { - if (ps.picture->anim) { - if ((ps.picture->next == NULL) || - (ps.picture->next->anim != ps.picture->anim)) - { - IMB_close_anim(ps.picture->anim); - } - } - - if (ps.picture->ibuf) { - IMB_freeImBuf(ps.picture->ibuf); - } - if (ps.picture->mem) { - MEM_freeN(ps.picture->mem); - } - - MEM_freeN((void *)ps.picture->name); - MEM_freeN(ps.picture); - } - - /* cleanup */ + while (pupdate_time()) { + PIL_sleep_ms(1); + } + ptottime -= swaptime; + playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep); + } /* else delete */ + else { + printf("error: can't play this image type\n"); + exit(0); + } + + if (ps.once) { + if (ps.picture->next == NULL) { + ps.wait2 = true; + } + else if (ps.picture->prev == NULL) { + ps.wait2 = true; + } + } + + ps.next_frame = ps.direction; + + while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0))) { + GHOST_DispatchEvents(g_WS.ghost_system); + } + if (ps.go == false) { + break; + } + change_frame(&ps); + if (!hasevent) { + PIL_sleep_ms(1); + } + if (ps.wait2) { + continue; + } + + ps.wait2 = ps.sstep; + + if (ps.wait2 == false && ps.stopped == false) { + ps.stopped = true; + } + + pupdate_time(); + + if (ps.picture && ps.next_frame) { + /* always at least set one step */ + while (ps.picture) { + ps.picture = playanim_step(ps.picture, ps.next_frame); + + if (ps.once && ps.picture != NULL) { + if (ps.picture->next == NULL) { + ps.wait2 = true; + } + else if (ps.picture->prev == NULL) { + ps.wait2 = true; + } + } + + if (ps.wait2 || ptottime < swaptime || ps.turbo || ps.noskip) { + break; + } + ptottime -= swaptime; + } + if (ps.picture == NULL && ps.sstep) { + ps.picture = playanim_step(ps.picture, ps.next_frame); + } + } + if (ps.go == false) { + break; + } + } + } + while ((ps.picture = BLI_pophead(&picsbase))) { + if (ps.picture->anim) { + if ((ps.picture->next == NULL) || (ps.picture->next->anim != ps.picture->anim)) { + IMB_close_anim(ps.picture->anim); + } + } + + if (ps.picture->ibuf) { + IMB_freeImBuf(ps.picture->ibuf); + } + if (ps.picture->mem) { + MEM_freeN(ps.picture->mem); + } + + MEM_freeN((void *)ps.picture->name); + MEM_freeN(ps.picture); + } + + /* cleanup */ #ifndef USE_IMB_CACHE - if (ibuf) { - IMB_freeImBuf(ibuf); - } + if (ibuf) { + IMB_freeImBuf(ibuf); + } #endif - BLI_freelistN(&picsbase); - BLI_freelistN(&inmempicsbase); - added_images = 0; + BLI_freelistN(&picsbase); + BLI_freelistN(&inmempicsbase); + added_images = 0; #ifdef WITH_AUDASPACE - if (playback_handle) { - AUD_Handle_stop(playback_handle); - playback_handle = NULL; - } - if (scrub_handle) { - AUD_Handle_stop(scrub_handle); - scrub_handle = NULL; - } - AUD_Sound_free(source); - source = NULL; + if (playback_handle) { + AUD_Handle_stop(playback_handle); + playback_handle = NULL; + } + if (scrub_handle) { + AUD_Handle_stop(scrub_handle); + scrub_handle = NULL; + } + AUD_Sound_free(source); + source = NULL; #endif - /* we still miss freeing a lot!, - * but many areas could skip initialization too for anim play */ + /* we still miss freeing a lot!, + * but many areas could skip initialization too for anim play */ - GPU_shader_free_builtin_shaders(); + GPU_shader_free_builtin_shaders(); - immDeactivate(); + immDeactivate(); - if (g_WS.gpu_context) { - GPU_context_active_set(g_WS.gpu_context); - GPU_context_discard(g_WS.gpu_context); - g_WS.gpu_context = NULL; - } + if (g_WS.gpu_context) { + GPU_context_active_set(g_WS.gpu_context); + GPU_context_discard(g_WS.gpu_context); + g_WS.gpu_context = NULL; + } - BLF_exit(); + BLF_exit(); - GPU_exit(); + GPU_exit(); - GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window); + GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window); - /* early exit, IMB and BKE should be exited only in end */ - if (ps.dropped_file[0]) { - BLI_strncpy(filepath, ps.dropped_file, sizeof(filepath)); - return filepath; - } + /* early exit, IMB and BKE should be exited only in end */ + if (ps.dropped_file[0]) { + BLI_strncpy(filepath, ps.dropped_file, sizeof(filepath)); + return filepath; + } - IMB_exit(); - BKE_images_exit(); - DEG_free_node_types(); + IMB_exit(); + BKE_images_exit(); + DEG_free_node_types(); - totblock = MEM_get_memory_blocks_in_use(); - if (totblock != 0) { - /* prints many bAKey, bArgument's which are tricky to fix */ + totblock = MEM_get_memory_blocks_in_use(); + if (totblock != 0) { + /* prints many bAKey, bArgument's which are tricky to fix */ #if 0 - printf("Error Totblock: %d\n", totblock); - MEM_printmemlist(); + printf("Error Totblock: %d\n", totblock); + MEM_printmemlist(); #endif - } + } - return NULL; + return NULL; } - void WM_main_playanim(int argc, const char **argv) { - const char *argv_next[2]; - bool looping = true; + const char *argv_next[2]; + bool looping = true; #ifdef WITH_AUDASPACE - { - AUD_DeviceSpecs specs; + { + AUD_DeviceSpecs specs; - specs.rate = AUD_RATE_48000; - specs.format = AUD_FORMAT_S16; - specs.channels = AUD_CHANNELS_STEREO; + specs.rate = AUD_RATE_48000; + specs.format = AUD_FORMAT_S16; + specs.channels = AUD_CHANNELS_STEREO; - AUD_initOnce(); + AUD_initOnce(); - if (!(audio_device = AUD_init("OpenAL", specs, 1024, "Blender"))) { - audio_device = AUD_init("Null", specs, 0, "Blender"); - } - } + if (!(audio_device = AUD_init("OpenAL", specs, 1024, "Blender"))) { + audio_device = AUD_init("Null", specs, 0, "Blender"); + } + } #endif - while (looping) { - const char *filepath = wm_main_playanim_intern(argc, argv); + while (looping) { + const char *filepath = wm_main_playanim_intern(argc, argv); - if (filepath) { /* use simple args */ - argv_next[0] = argv[0]; - argv_next[1] = filepath; - argc = 2; + if (filepath) { /* use simple args */ + argv_next[0] = argv[0]; + argv_next[1] = filepath; + argc = 2; - /* continue with new args */ - argv = argv_next; - } - else { - looping = false; - } - } + /* continue with new args */ + argv = argv_next; + } + else { + looping = false; + } + } #ifdef WITH_AUDASPACE - AUD_exit(audio_device); - AUD_exitOnce(); + AUD_exit(audio_device); + AUD_exitOnce(); #endif } diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 6691a7f453b..47f860e7667 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -21,7 +21,6 @@ * \ingroup wm */ - #include <stdlib.h> #include <string.h> @@ -58,229 +57,226 @@ static eGPUInterlaceShader interlace_gpu_id_from_type(eStereo3dInterlaceType interlace_type) { - switch (interlace_type) { - case S3D_INTERLACE_ROW: - return GPU_SHADER_INTERLACE_ROW; - case S3D_INTERLACE_COLUMN: - return GPU_SHADER_INTERLACE_COLUMN; - case S3D_INTERLACE_CHECKERBOARD: - default: - return GPU_SHADER_INTERLACE_CHECKER; - } + switch (interlace_type) { + case S3D_INTERLACE_ROW: + return GPU_SHADER_INTERLACE_ROW; + case S3D_INTERLACE_COLUMN: + return GPU_SHADER_INTERLACE_COLUMN; + case S3D_INTERLACE_CHECKERBOARD: + default: + return GPU_SHADER_INTERLACE_CHECKER; + } } void wm_stereo3d_draw_interlace(wmWindow *win, ARegion *ar) { - bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0; - enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type; + bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0; + enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type; - /* wmOrtho for the screen has this same offset */ - float halfx = GLA_PIXEL_OFS / ar->winx; - float halfy = GLA_PIXEL_OFS / ar->winy; + /* wmOrtho for the screen has this same offset */ + float halfx = GLA_PIXEL_OFS / ar->winx; + float halfy = GLA_PIXEL_OFS / ar->winy; - GPUVertFormat *format = immVertexFormat(); - uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPUVertFormat *format = immVertexFormat(); + uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - /* leave GL_TEXTURE0 as the latest active texture */ - for (int view = 1; view >= 0; view--) { - GPUTexture *texture = wm_draw_region_texture(ar, view); - glActiveTexture(GL_TEXTURE0 + view); - glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); - } + /* leave GL_TEXTURE0 as the latest active texture */ + for (int view = 1; view >= 0; view--) { + GPUTexture *texture = wm_draw_region_texture(ar, view); + glActiveTexture(GL_TEXTURE0 + view); + glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); + } - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_INTERLACE); - immUniform1i("image_a", (swap) ? 1 : 0); - immUniform1i("image_b", (swap) ? 0 : 1); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_INTERLACE); + immUniform1i("image_a", (swap) ? 1 : 0); + immUniform1i("image_b", (swap) ? 0 : 1); - immUniform1i("interlace_id", interlace_gpu_id_from_type(interlace_type)); + immUniform1i("interlace_id", interlace_gpu_id_from_type(interlace_type)); - immBegin(GPU_PRIM_TRI_FAN, 4); + immBegin(GPU_PRIM_TRI_FAN, 4); - immAttr2f(texcoord, halfx, halfy); - immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymin); + immAttr2f(texcoord, halfx, halfy); + immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymin); - immAttr2f(texcoord, 1.0f + halfx, halfy); - immVertex2f(pos, ar->winrct.xmax + 1, ar->winrct.ymin); + immAttr2f(texcoord, 1.0f + halfx, halfy); + immVertex2f(pos, ar->winrct.xmax + 1, ar->winrct.ymin); - immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy); - immVertex2f(pos, ar->winrct.xmax + 1, ar->winrct.ymax + 1); + immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy); + immVertex2f(pos, ar->winrct.xmax + 1, ar->winrct.ymax + 1); - immAttr2f(texcoord, halfx, 1.0f + halfy); - immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymax + 1); + immAttr2f(texcoord, halfx, 1.0f + halfy); + immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymax + 1); - immEnd(); - immUnbindProgram(); + immEnd(); + immUnbindProgram(); - for (int view = 1; view >= 0; view--) { - glActiveTexture(GL_TEXTURE0 + view); - glBindTexture(GL_TEXTURE_2D, 0); - } + for (int view = 1; view >= 0; view--) { + glActiveTexture(GL_TEXTURE0 + view); + glBindTexture(GL_TEXTURE_2D, 0); + } } void wm_stereo3d_draw_anaglyph(wmWindow *win, ARegion *ar) { - for (int view = 0; view < 2; view ++) { - int bit = view + 1; - - switch (win->stereo3d_format->anaglyph_type) { - case S3D_ANAGLYPH_REDCYAN: - glColorMask((1&bit) ? GL_TRUE : GL_FALSE, - (2&bit) ? GL_TRUE : GL_FALSE, - (2&bit) ? GL_TRUE : GL_FALSE, - GL_FALSE); - break; - case S3D_ANAGLYPH_GREENMAGENTA: - glColorMask((2&bit) ? GL_TRUE : GL_FALSE, - (1&bit) ? GL_TRUE : GL_FALSE, - (2&bit) ? GL_TRUE : GL_FALSE, - GL_FALSE); - break; - case S3D_ANAGLYPH_YELLOWBLUE: - glColorMask((1&bit) ? GL_TRUE : GL_FALSE, - (1&bit) ? GL_TRUE : GL_FALSE, - (2&bit) ? GL_TRUE : GL_FALSE, - GL_FALSE); - break; - } - - wm_draw_region_blend(ar, view, false); - } - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + for (int view = 0; view < 2; view++) { + int bit = view + 1; + + switch (win->stereo3d_format->anaglyph_type) { + case S3D_ANAGLYPH_REDCYAN: + glColorMask((1 & bit) ? GL_TRUE : GL_FALSE, + (2 & bit) ? GL_TRUE : GL_FALSE, + (2 & bit) ? GL_TRUE : GL_FALSE, + GL_FALSE); + break; + case S3D_ANAGLYPH_GREENMAGENTA: + glColorMask((2 & bit) ? GL_TRUE : GL_FALSE, + (1 & bit) ? GL_TRUE : GL_FALSE, + (2 & bit) ? GL_TRUE : GL_FALSE, + GL_FALSE); + break; + case S3D_ANAGLYPH_YELLOWBLUE: + glColorMask((1 & bit) ? GL_TRUE : GL_FALSE, + (1 & bit) ? GL_TRUE : GL_FALSE, + (2 & bit) ? GL_TRUE : GL_FALSE, + GL_FALSE); + break; + } + + wm_draw_region_blend(ar, view, false); + } + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } void wm_stereo3d_draw_sidebyside(wmWindow *win, int view) { - bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0; + bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0; - GPUVertFormat *format = immVertexFormat(); - uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPUVertFormat *format = immVertexFormat(); + uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE); - int soffx = WM_window_pixels_x(win) * 0.5f; - if (view == STEREO_LEFT_ID) { - if (!cross_eyed) { - soffx = 0; - } - } - else { //RIGHT_LEFT_ID - if (cross_eyed) { - soffx = 0; - } - } + int soffx = WM_window_pixels_x(win) * 0.5f; + if (view == STEREO_LEFT_ID) { + if (!cross_eyed) { + soffx = 0; + } + } + else { //RIGHT_LEFT_ID + if (cross_eyed) { + soffx = 0; + } + } - const int sizex = WM_window_pixels_x(win); - const int sizey = WM_window_pixels_y(win); + const int sizex = WM_window_pixels_x(win); + const int sizey = WM_window_pixels_y(win); - /* wmOrtho for the screen has this same offset */ - const float halfx = GLA_PIXEL_OFS / sizex; - const float halfy = GLA_PIXEL_OFS / sizex; + /* wmOrtho for the screen has this same offset */ + const float halfx = GLA_PIXEL_OFS / sizex; + const float halfy = GLA_PIXEL_OFS / sizex; - immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */ + immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */ - immBegin(GPU_PRIM_TRI_FAN, 4); + immBegin(GPU_PRIM_TRI_FAN, 4); - immAttr2f(texcoord, halfx, halfy); - immVertex2f(pos, soffx, 0.0f); + immAttr2f(texcoord, halfx, halfy); + immVertex2f(pos, soffx, 0.0f); - immAttr2f(texcoord, 1.0f + halfx, halfy); - immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f); + immAttr2f(texcoord, 1.0f + halfx, halfy); + immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f); - immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy); - immVertex2f(pos, soffx + (sizex * 0.5f), sizey); + immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy); + immVertex2f(pos, soffx + (sizex * 0.5f), sizey); - immAttr2f(texcoord, halfx, 1.0f + halfy); - immVertex2f(pos, soffx, sizey); + immAttr2f(texcoord, halfx, 1.0f + halfy); + immVertex2f(pos, soffx, sizey); - immEnd(); + immEnd(); - immUnbindProgram(); + immUnbindProgram(); } void wm_stereo3d_draw_topbottom(wmWindow *win, int view) { - GPUVertFormat *format = immVertexFormat(); - uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPUVertFormat *format = immVertexFormat(); + uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE); - int soffy; - if (view == STEREO_LEFT_ID) { - soffy = WM_window_pixels_y(win) * 0.5f; - } - else { /* STEREO_RIGHT_ID */ - soffy = 0; - } + int soffy; + if (view == STEREO_LEFT_ID) { + soffy = WM_window_pixels_y(win) * 0.5f; + } + else { /* STEREO_RIGHT_ID */ + soffy = 0; + } - const int sizex = WM_window_pixels_x(win); - const int sizey = WM_window_pixels_y(win); + const int sizex = WM_window_pixels_x(win); + const int sizey = WM_window_pixels_y(win); - /* wmOrtho for the screen has this same offset */ - const float halfx = GLA_PIXEL_OFS / sizex; - const float halfy = GLA_PIXEL_OFS / sizex; + /* wmOrtho for the screen has this same offset */ + const float halfx = GLA_PIXEL_OFS / sizex; + const float halfy = GLA_PIXEL_OFS / sizex; - immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */ + immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */ - immBegin(GPU_PRIM_TRI_FAN, 4); + immBegin(GPU_PRIM_TRI_FAN, 4); - immAttr2f(texcoord, halfx, halfy); - immVertex2f(pos, 0.0f, soffy); + immAttr2f(texcoord, halfx, halfy); + immVertex2f(pos, 0.0f, soffy); - immAttr2f(texcoord, 1.0f + halfx, halfy); - immVertex2f(pos, sizex, soffy); + immAttr2f(texcoord, 1.0f + halfx, halfy); + immVertex2f(pos, sizex, soffy); - immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy); - immVertex2f(pos, sizex, soffy + (sizey * 0.5f)); + immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy); + immVertex2f(pos, sizex, soffy + (sizey * 0.5f)); - immAttr2f(texcoord, halfx, 1.0f + halfy); - immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f)); + immAttr2f(texcoord, halfx, 1.0f + halfy); + immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f)); - immEnd(); + immEnd(); - immUnbindProgram(); + immUnbindProgram(); } - static bool wm_stereo3d_quadbuffer_supported(void) { - GLboolean stereo = GL_FALSE; - glGetBooleanv(GL_STEREO, &stereo); - return stereo == GL_TRUE; + GLboolean stereo = GL_FALSE; + glGetBooleanv(GL_STEREO, &stereo); + return stereo == GL_TRUE; } static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display) { - return ELEM(stereo_display, - S3D_DISPLAY_SIDEBYSIDE, - S3D_DISPLAY_TOPBOTTOM); + return ELEM(stereo_display, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM); } bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) { - const bScreen *screen = WM_window_get_active_screen(win); - const Scene *scene = WM_window_get_active_scene(win); - - /* some 3d methods change the window arrangement, thus they shouldn't - * toggle on/off just because there is no 3d elements being drawn */ - if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { - return GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen; - } - - if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen, scene) == false)) { - return false; - } - - /* some 3d methods change the window arrangement, thus they shouldn't - * toggle on/off just because there is no 3d elements being drawn */ - if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { - return GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen; - } - - return true; + const bScreen *screen = WM_window_get_active_screen(win); + const Scene *scene = WM_window_get_active_scene(win); + + /* some 3d methods change the window arrangement, thus they shouldn't + * toggle on/off just because there is no 3d elements being drawn */ + if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { + return GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen; + } + + if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen, scene) == false)) { + return false; + } + + /* some 3d methods change the window arrangement, thus they shouldn't + * toggle on/off just because there is no 3d elements being drawn */ + if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { + return GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen; + } + + return true; } /** @@ -288,242 +284,240 @@ bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) */ void wm_stereo3d_mouse_offset_apply(wmWindow *win, int *r_mouse_xy) { - if (!WM_stereo3d_enabled(win, false)) { - return; - } - - if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) { - const int half_x = win->sizex / 2; - /* right half of the screen */ - if (r_mouse_xy[0] > half_x) { - r_mouse_xy[0] -= half_x; - } - r_mouse_xy[0] *= 2; - } - else if (win->stereo3d_format->display_mode == S3D_DISPLAY_TOPBOTTOM) { - const int half_y = win->sizey / 2; - /* upper half of the screen */ - if (r_mouse_xy[1] > half_y) { - r_mouse_xy[1] -= half_y; - } - r_mouse_xy[1] *= 2; - } + if (!WM_stereo3d_enabled(win, false)) { + return; + } + + if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) { + const int half_x = win->sizex / 2; + /* right half of the screen */ + if (r_mouse_xy[0] > half_x) { + r_mouse_xy[0] -= half_x; + } + r_mouse_xy[0] *= 2; + } + else if (win->stereo3d_format->display_mode == S3D_DISPLAY_TOPBOTTOM) { + const int half_y = win->sizey / 2; + /* upper half of the screen */ + if (r_mouse_xy[1] > half_y) { + r_mouse_xy[1] -= half_y; + } + r_mouse_xy[1] *= 2; + } } /************************** Stereo 3D operator **********************************/ typedef struct Stereo3dData { - Stereo3dFormat stereo3d_format; + Stereo3dFormat stereo3d_format; } Stereo3dData; static bool wm_stereo3d_set_properties(bContext *UNUSED(C), wmOperator *op) { - Stereo3dData *s3dd = op->customdata; - Stereo3dFormat *s3d = &s3dd->stereo3d_format; - PropertyRNA *prop; - bool is_set = false; - - prop = RNA_struct_find_property(op->ptr, "display_mode"); - if (RNA_property_is_set(op->ptr, prop)) { - s3d->display_mode = RNA_property_enum_get(op->ptr, prop); - is_set = true; - } - - prop = RNA_struct_find_property(op->ptr, "anaglyph_type"); - if (RNA_property_is_set(op->ptr, prop)) { - s3d->anaglyph_type = RNA_property_enum_get(op->ptr, prop); - is_set = true; - } - - prop = RNA_struct_find_property(op->ptr, "interlace_type"); - if (RNA_property_is_set(op->ptr, prop)) { - s3d->interlace_type = RNA_property_enum_get(op->ptr, prop); - is_set = true; - } - - prop = RNA_struct_find_property(op->ptr, "use_interlace_swap"); - if (RNA_property_is_set(op->ptr, prop)) { - if (RNA_property_boolean_get(op->ptr, prop)) { - s3d->flag |= S3D_INTERLACE_SWAP; - } - else { - s3d->flag &= ~S3D_INTERLACE_SWAP; - } - is_set = true; - } - - prop = RNA_struct_find_property(op->ptr, "use_sidebyside_crosseyed"); - if (RNA_property_is_set(op->ptr, prop)) { - if (RNA_property_boolean_get(op->ptr, prop)) { - s3d->flag |= S3D_SIDEBYSIDE_CROSSEYED; - } - else { - s3d->flag &= ~S3D_SIDEBYSIDE_CROSSEYED; - } - is_set = true; - } - - return is_set; + Stereo3dData *s3dd = op->customdata; + Stereo3dFormat *s3d = &s3dd->stereo3d_format; + PropertyRNA *prop; + bool is_set = false; + + prop = RNA_struct_find_property(op->ptr, "display_mode"); + if (RNA_property_is_set(op->ptr, prop)) { + s3d->display_mode = RNA_property_enum_get(op->ptr, prop); + is_set = true; + } + + prop = RNA_struct_find_property(op->ptr, "anaglyph_type"); + if (RNA_property_is_set(op->ptr, prop)) { + s3d->anaglyph_type = RNA_property_enum_get(op->ptr, prop); + is_set = true; + } + + prop = RNA_struct_find_property(op->ptr, "interlace_type"); + if (RNA_property_is_set(op->ptr, prop)) { + s3d->interlace_type = RNA_property_enum_get(op->ptr, prop); + is_set = true; + } + + prop = RNA_struct_find_property(op->ptr, "use_interlace_swap"); + if (RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + s3d->flag |= S3D_INTERLACE_SWAP; + } + else { + s3d->flag &= ~S3D_INTERLACE_SWAP; + } + is_set = true; + } + + prop = RNA_struct_find_property(op->ptr, "use_sidebyside_crosseyed"); + if (RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + s3d->flag |= S3D_SIDEBYSIDE_CROSSEYED; + } + else { + s3d->flag &= ~S3D_SIDEBYSIDE_CROSSEYED; + } + is_set = true; + } + + return is_set; } static void wm_stereo3d_set_init(bContext *C, wmOperator *op) { - Stereo3dData *s3dd; - wmWindow *win = CTX_wm_window(C); + Stereo3dData *s3dd; + wmWindow *win = CTX_wm_window(C); - op->customdata = s3dd = MEM_callocN(sizeof(Stereo3dData), __func__); + op->customdata = s3dd = MEM_callocN(sizeof(Stereo3dData), __func__); - /* store the original win stereo 3d settings in case of cancel */ - s3dd->stereo3d_format = *win->stereo3d_format; + /* store the original win stereo 3d settings in case of cancel */ + s3dd->stereo3d_format = *win->stereo3d_format; } int wm_stereo3d_set_exec(bContext *C, wmOperator *op) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win_src = CTX_wm_window(C); - wmWindow *win_dst = NULL; - const bool is_fullscreen = WM_window_is_fullscreen(win_src); - char prev_display_mode = win_src->stereo3d_format->display_mode; - Stereo3dData *s3dd; - bool ok = true; - - if (G.background) { - return OPERATOR_CANCELLED; - } - - if (op->customdata == NULL) { - /* no invoke means we need to set the operator properties here */ - wm_stereo3d_set_init(C, op); - wm_stereo3d_set_properties(C, op); - } - - s3dd = op->customdata; - *win_src->stereo3d_format = s3dd->stereo3d_format; - - if (prev_display_mode == S3D_DISPLAY_PAGEFLIP && - prev_display_mode != win_src->stereo3d_format->display_mode) - { - /* in case the hardware supports pageflip but not the display */ - if ((win_dst = wm_window_copy_test(C, win_src, false, false))) { - /* pass */ - } - else { - BKE_report(op->reports, RPT_ERROR, - "Failed to create a window without quad-buffer support, you may experience flickering"); - ok = false; - } - } - else if (win_src->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { - const bScreen *screen = WM_window_get_active_screen(win_src); - - /* ED_workspace_layout_duplicate() can't handle other cases yet T44688 */ - if (screen->state != SCREENNORMAL) { - BKE_report(op->reports, RPT_ERROR, - "Failed to switch to Time Sequential mode when in fullscreen"); - ok = false; - } - /* pageflip requires a new window to be created with the proper OS flags */ - else if ((win_dst = wm_window_copy_test(C, win_src, false, false))) { - if (wm_stereo3d_quadbuffer_supported()) { - BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created"); - } - else { - wm_window_close(C, wm, win_dst); - win_dst = NULL; - BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); - ok = false; - } - } - else { - BKE_report(op->reports, RPT_ERROR, - "Failed to create a window compatible with the time sequential display method"); - ok = false; - } - } - - if (wm_stereo3d_is_fullscreen_required(s3dd->stereo3d_format.display_mode)) { - if (!is_fullscreen) { - BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); - } - } - - MEM_freeN(op->customdata); - - if (ok) { - if (win_dst) { - wm_window_close(C, wm, win_src); - } - - WM_event_add_notifier(C, NC_WINDOW, NULL); - return OPERATOR_FINISHED; - } - else { - /* without this, the popup won't be freed freed properly T44688 */ - CTX_wm_window_set(C, win_src); - win_src->stereo3d_format->display_mode = prev_display_mode; - return OPERATOR_CANCELLED; - } + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win_src = CTX_wm_window(C); + wmWindow *win_dst = NULL; + const bool is_fullscreen = WM_window_is_fullscreen(win_src); + char prev_display_mode = win_src->stereo3d_format->display_mode; + Stereo3dData *s3dd; + bool ok = true; + + if (G.background) { + return OPERATOR_CANCELLED; + } + + if (op->customdata == NULL) { + /* no invoke means we need to set the operator properties here */ + wm_stereo3d_set_init(C, op); + wm_stereo3d_set_properties(C, op); + } + + s3dd = op->customdata; + *win_src->stereo3d_format = s3dd->stereo3d_format; + + if (prev_display_mode == S3D_DISPLAY_PAGEFLIP && + prev_display_mode != win_src->stereo3d_format->display_mode) { + /* in case the hardware supports pageflip but not the display */ + if ((win_dst = wm_window_copy_test(C, win_src, false, false))) { + /* pass */ + } + else { + BKE_report( + op->reports, + RPT_ERROR, + "Failed to create a window without quad-buffer support, you may experience flickering"); + ok = false; + } + } + else if (win_src->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + const bScreen *screen = WM_window_get_active_screen(win_src); + + /* ED_workspace_layout_duplicate() can't handle other cases yet T44688 */ + if (screen->state != SCREENNORMAL) { + BKE_report( + op->reports, RPT_ERROR, "Failed to switch to Time Sequential mode when in fullscreen"); + ok = false; + } + /* pageflip requires a new window to be created with the proper OS flags */ + else if ((win_dst = wm_window_copy_test(C, win_src, false, false))) { + if (wm_stereo3d_quadbuffer_supported()) { + BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created"); + } + else { + wm_window_close(C, wm, win_dst); + win_dst = NULL; + BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); + ok = false; + } + } + else { + BKE_report(op->reports, + RPT_ERROR, + "Failed to create a window compatible with the time sequential display method"); + ok = false; + } + } + + if (wm_stereo3d_is_fullscreen_required(s3dd->stereo3d_format.display_mode)) { + if (!is_fullscreen) { + BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); + } + } + + MEM_freeN(op->customdata); + + if (ok) { + if (win_dst) { + wm_window_close(C, wm, win_src); + } + + WM_event_add_notifier(C, NC_WINDOW, NULL); + return OPERATOR_FINISHED; + } + else { + /* without this, the popup won't be freed freed properly T44688 */ + CTX_wm_window_set(C, win_src); + win_src->stereo3d_format->display_mode = prev_display_mode; + return OPERATOR_CANCELLED; + } } int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - wm_stereo3d_set_init(C, op); - - if (wm_stereo3d_set_properties(C, op)) { - return wm_stereo3d_set_exec(C, op); - } - else { - return WM_operator_props_dialog_popup(C, op, 250, 100); - } + wm_stereo3d_set_init(C, op); + + if (wm_stereo3d_set_properties(C, op)) { + return wm_stereo3d_set_exec(C, op); + } + else { + return WM_operator_props_dialog_popup(C, op, 250, 100); + } } void wm_stereo3d_set_draw(bContext *UNUSED(C), wmOperator *op) { - Stereo3dData *s3dd = op->customdata; - PointerRNA stereo3d_format_ptr; - uiLayout *layout = op->layout; - uiLayout *col; - - RNA_pointer_create(NULL, &RNA_Stereo3dDisplay, &s3dd->stereo3d_format, &stereo3d_format_ptr); - - col = uiLayoutColumn(layout, false); - uiItemR(col, &stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE); - - switch (s3dd->stereo3d_format.display_mode) { - case S3D_DISPLAY_ANAGLYPH: - { - uiItemR(col, &stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE); - break; - } - case S3D_DISPLAY_INTERLACE: - { - uiItemR(col, &stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE); - uiItemR(col, &stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE); - break; - } - case S3D_DISPLAY_SIDEBYSIDE: - { - uiItemR(col, &stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE); - /* fall-through */ - } - case S3D_DISPLAY_PAGEFLIP: - case S3D_DISPLAY_TOPBOTTOM: - default: - { - break; - } - } + Stereo3dData *s3dd = op->customdata; + PointerRNA stereo3d_format_ptr; + uiLayout *layout = op->layout; + uiLayout *col; + + RNA_pointer_create(NULL, &RNA_Stereo3dDisplay, &s3dd->stereo3d_format, &stereo3d_format_ptr); + + col = uiLayoutColumn(layout, false); + uiItemR(col, &stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE); + + switch (s3dd->stereo3d_format.display_mode) { + case S3D_DISPLAY_ANAGLYPH: { + uiItemR(col, &stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE); + break; + } + case S3D_DISPLAY_INTERLACE: { + uiItemR(col, &stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE); + uiItemR(col, &stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE); + break; + } + case S3D_DISPLAY_SIDEBYSIDE: { + uiItemR(col, &stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE); + /* fall-through */ + } + case S3D_DISPLAY_PAGEFLIP: + case S3D_DISPLAY_TOPBOTTOM: + default: { + break; + } + } } bool wm_stereo3d_set_check(bContext *UNUSED(C), wmOperator *UNUSED(op)) { - /* the check function guarantees that the menu is updated to show the - * sub-options when an enum change (e.g., it shows the anaglyph options - * when anaglyph is on, and the interlace options when this is on */ - return true; + /* the check function guarantees that the menu is updated to show the + * sub-options when an enum change (e.g., it shows the anaglyph options + * when anaglyph is on, and the interlace options when this is on */ + return true; } void wm_stereo3d_set_cancel(bContext *UNUSED(C), wmOperator *op) { - MEM_freeN(op->customdata); - op->customdata = NULL; + MEM_freeN(op->customdata); + op->customdata = NULL; } diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 6f856e16047..2f40947b395 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -37,99 +37,105 @@ void wmViewport(const rcti *winrct) { - int width = BLI_rcti_size_x(winrct) + 1; - int height = BLI_rcti_size_y(winrct) + 1; + int width = BLI_rcti_size_x(winrct) + 1; + int height = BLI_rcti_size_y(winrct) + 1; - glViewport(winrct->xmin, winrct->ymin, width, height); - glScissor(winrct->xmin, winrct->ymin, width, height); + glViewport(winrct->xmin, winrct->ymin, width, height); + glScissor(winrct->xmin, winrct->ymin, width, height); - wmOrtho2_pixelspace(width, height); - GPU_matrix_identity_set(); + wmOrtho2_pixelspace(width, height); + GPU_matrix_identity_set(); } void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct) { - /* Setup part of the viewport for partial redraw. */ - bool scissor_pad; - - if (partialrct->xmin == partialrct->xmax) { - /* Full region. */ - *drawrct = *winrct; - scissor_pad = true; - } - else { - /* Partial redraw, clipped to region. */ - BLI_rcti_isect(winrct, partialrct, drawrct); - scissor_pad = false; - } - - int x = drawrct->xmin - winrct->xmin; - int y = drawrct->ymin - winrct->ymin; - int width = BLI_rcti_size_x(winrct) + 1; - int height = BLI_rcti_size_y(winrct) + 1; - - int scissor_width = BLI_rcti_size_x(drawrct); - int scissor_height = BLI_rcti_size_y(drawrct); - - /* Partial redraw rect uses different convention than region rect, - * so compensate for that here. One pixel offset is noticeable with - * viewport border render. */ - if (scissor_pad) { - scissor_width += 1; - scissor_height += 1; - } - - glViewport(0, 0, width, height); - glScissor(x, y, scissor_width, scissor_height); - - wmOrtho2_pixelspace(width, height); - GPU_matrix_identity_set(); + /* Setup part of the viewport for partial redraw. */ + bool scissor_pad; + + if (partialrct->xmin == partialrct->xmax) { + /* Full region. */ + *drawrct = *winrct; + scissor_pad = true; + } + else { + /* Partial redraw, clipped to region. */ + BLI_rcti_isect(winrct, partialrct, drawrct); + scissor_pad = false; + } + + int x = drawrct->xmin - winrct->xmin; + int y = drawrct->ymin - winrct->ymin; + int width = BLI_rcti_size_x(winrct) + 1; + int height = BLI_rcti_size_y(winrct) + 1; + + int scissor_width = BLI_rcti_size_x(drawrct); + int scissor_height = BLI_rcti_size_y(drawrct); + + /* Partial redraw rect uses different convention than region rect, + * so compensate for that here. One pixel offset is noticeable with + * viewport border render. */ + if (scissor_pad) { + scissor_width += 1; + scissor_height += 1; + } + + glViewport(0, 0, width, height); + glScissor(x, y, scissor_width, scissor_height); + + wmOrtho2_pixelspace(width, height); + GPU_matrix_identity_set(); } void wmWindowViewport(wmWindow *win) { - int width = WM_window_pixels_x(win); - int height = WM_window_pixels_y(win); + int width = WM_window_pixels_x(win); + int height = WM_window_pixels_y(win); - glViewport(0, 0, width, height); - glScissor(0, 0, width, height); + glViewport(0, 0, width, height); + glScissor(0, 0, width, height); - wmOrtho2_pixelspace(width, height); - GPU_matrix_identity_set(); + wmOrtho2_pixelspace(width, height); + GPU_matrix_identity_set(); } void wmOrtho2(float x1, float x2, float y1, float y2) { - /* prevent opengl from generating errors */ - if (x2 == x1) { - x2 += 1.0f; - } - if (y2 == y1) { - y2 += 1.0f; - } - - GPU_matrix_ortho_set(x1, x2, y1, y2, -100, 100); + /* prevent opengl from generating errors */ + if (x2 == x1) { + x2 += 1.0f; + } + if (y2 == y1) { + y2 += 1.0f; + } + + GPU_matrix_ortho_set(x1, x2, y1, y2, -100, 100); } static void wmOrtho2_offset(const float x, const float y, const float ofs) { - wmOrtho2(ofs, x + ofs, ofs, y + ofs); + wmOrtho2(ofs, x + ofs, ofs, y + ofs); } /* Default pixel alignment for regions. */ void wmOrtho2_region_pixelspace(const ARegion *ar) { - wmOrtho2_offset(ar->winx, ar->winy, -0.01f); + wmOrtho2_offset(ar->winx, ar->winy, -0.01f); } void wmOrtho2_pixelspace(const float x, const float y) { - wmOrtho2_offset(x, y, -GLA_PIXEL_OFS); + wmOrtho2_offset(x, y, -GLA_PIXEL_OFS); } void wmGetProjectionMatrix(float mat[4][4], const rcti *winrct) { - int width = BLI_rcti_size_x(winrct) + 1; - int height = BLI_rcti_size_y(winrct) + 1; - orthographic_m4(mat, -GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS, -100, 100); + int width = BLI_rcti_size_x(winrct) + 1; + int height = BLI_rcti_size_y(winrct) + 1; + orthographic_m4(mat, + -GLA_PIXEL_OFS, + (float)width - GLA_PIXEL_OFS, + -GLA_PIXEL_OFS, + (float)height - GLA_PIXEL_OFS, + -100, + 100); } diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index 806bd028295..a867a17f529 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -51,14 +51,18 @@ #include "WM_api.h" #include "WM_types.h" #include "WM_message.h" -#include "WM_toolsystem.h" /* own include */ - -static void toolsystem_reinit_with_toolref( - bContext *C, WorkSpace *UNUSED(workspace), bToolRef *tref); -static bToolRef *toolsystem_reinit_ensure_toolref( - bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *default_tool); -static void toolsystem_refresh_screen_from_active_tool( - Main *bmain, WorkSpace *workspace, bToolRef *tref); +#include "WM_toolsystem.h" /* own include */ + +static void toolsystem_reinit_with_toolref(bContext *C, + WorkSpace *UNUSED(workspace), + bToolRef *tref); +static bToolRef *toolsystem_reinit_ensure_toolref(bContext *C, + WorkSpace *workspace, + const bToolKey *tkey, + const char *default_tool); +static void toolsystem_refresh_screen_from_active_tool(Main *bmain, + WorkSpace *workspace, + bToolRef *tref); /* -------------------------------------------------------------------- */ /** \name Tool Reference API @@ -66,116 +70,111 @@ static void toolsystem_refresh_screen_from_active_tool( struct bToolRef *WM_toolsystem_ref_from_context(struct bContext *C) { - WorkSpace *workspace = CTX_wm_workspace(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - ScrArea *sa = CTX_wm_area(C); - if (((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) { - return NULL; - } - const bToolKey tkey = { - .space_type = sa->spacetype, - .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), - }; - bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey); - /* We could return 'sa->runtime.tool' in this case. */ - if (sa->runtime.is_tool_set) { - BLI_assert(tref == sa->runtime.tool); - } - return tref; + WorkSpace *workspace = CTX_wm_workspace(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + ScrArea *sa = CTX_wm_area(C); + if (((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) { + return NULL; + } + const bToolKey tkey = { + .space_type = sa->spacetype, + .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), + }; + bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey); + /* We could return 'sa->runtime.tool' in this case. */ + if (sa->runtime.is_tool_set) { + BLI_assert(tref == sa->runtime.tool); + } + return tref; } struct bToolRef_Runtime *WM_toolsystem_runtime_from_context(struct bContext *C) { - bToolRef *tref = WM_toolsystem_ref_from_context(C); - return tref ? tref->runtime : NULL; + bToolRef *tref = WM_toolsystem_ref_from_context(C); + return tref ? tref->runtime : NULL; } bToolRef *WM_toolsystem_ref_find(WorkSpace *workspace, const bToolKey *tkey) { - BLI_assert((1 << tkey->space_type) & WM_TOOLSYSTEM_SPACE_MASK); - LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { - if ((tref->space_type == tkey->space_type) && - (tref->mode == tkey->mode)) - { - return tref; - } - } - return NULL; + BLI_assert((1 << tkey->space_type) & WM_TOOLSYSTEM_SPACE_MASK); + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + if ((tref->space_type == tkey->space_type) && (tref->mode == tkey->mode)) { + return tref; + } + } + return NULL; } bToolRef_Runtime *WM_toolsystem_runtime_find(WorkSpace *workspace, const bToolKey *tkey) { - bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); - return tref ? tref->runtime : NULL; + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + return tref ? tref->runtime : NULL; } -bool WM_toolsystem_ref_ensure( - struct WorkSpace *workspace, const bToolKey *tkey, - bToolRef **r_tref) +bool WM_toolsystem_ref_ensure(struct WorkSpace *workspace, const bToolKey *tkey, bToolRef **r_tref) { - bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); - if (tref) { - *r_tref = tref; - return false; - } - tref = MEM_callocN(sizeof(*tref), __func__); - BLI_addhead(&workspace->tools, tref); - tref->space_type = tkey->space_type; - tref->mode = tkey->mode; - *r_tref = tref; - return true; + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + if (tref) { + *r_tref = tref; + return false; + } + tref = MEM_callocN(sizeof(*tref), __func__); + BLI_addhead(&workspace->tools, tref); + tref->space_type = tkey->space_type; + tref->mode = tkey->mode; + *r_tref = tref; + return true; } /** \} */ - static void toolsystem_unlink_ref(bContext *C, WorkSpace *workspace, bToolRef *tref) { - bToolRef_Runtime *tref_rt = tref->runtime; + bToolRef_Runtime *tref_rt = tref->runtime; - if (tref_rt->gizmo_group[0]) { - wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false); - if (gzgt != NULL) { - bool found = false; + if (tref_rt->gizmo_group[0]) { + wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false); + if (gzgt != NULL) { + bool found = false; - /* TODO(campbell) */ - Main *bmain = CTX_data_main(C); + /* TODO(campbell) */ + Main *bmain = CTX_data_main(C); #if 0 - wmWindowManager *wm = bmain->wm.first; - /* Check another workspace isn't using this tool. */ - for (wmWindow *win = wm->windows.first; win; win = win->next) { - const WorkSpace *workspace_iter = WM_window_get_active_workspace(win); - if (workspace != workspace_iter) { - if (STREQ(workspace->tool.gizmo_group, workspace_iter->tool.gizmo_group)) { - found = true; - break; - } - } - } + wmWindowManager *wm = bmain->wm.first; + /* Check another workspace isn't using this tool. */ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + const WorkSpace *workspace_iter = WM_window_get_active_workspace(win); + if (workspace != workspace_iter) { + if (STREQ(workspace->tool.gizmo_group, workspace_iter->tool.gizmo_group)) { + found = true; + break; + } + } + } #else - UNUSED_VARS(workspace); + UNUSED_VARS(workspace); #endif - if (!found) { - wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params); - WM_gizmomaptype_group_unlink(C, bmain, gzmap_type, gzgt); - } - } - } + if (!found) { + wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params); + WM_gizmomaptype_group_unlink(C, bmain, gzmap_type, gzgt); + } + } + } } void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace, const bToolKey *tkey) { - bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); - if (tref && tref->runtime) { - toolsystem_unlink_ref(C, workspace, tref); - } + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + if (tref && tref->runtime) { + toolsystem_unlink_ref(C, workspace, tref); + } } static void toolsystem_ref_link__refresh_image_uv_sculpt(bContext *C, Scene *scene) { - PointerRNA ptr; - RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &ptr); - PropertyRNA *prop = RNA_struct_find_property(&ptr, "use_uv_sculpt"); - RNA_property_update(C, &ptr, prop); + PointerRNA ptr; + RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &ptr); + PropertyRNA *prop = RNA_struct_find_property(&ptr, "use_uv_sculpt"); + RNA_property_update(C, &ptr, prop); } /** @@ -183,261 +182,252 @@ static void toolsystem_ref_link__refresh_image_uv_sculpt(bContext *C, Scene *sce */ static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tref) { - bToolRef_Runtime *tref_rt = tref->runtime; - if (tref_rt->gizmo_group[0]) { - const char *idname = tref_rt->gizmo_group; - wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false); - if (gzgt != NULL) { - if ((gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_INIT) == 0) { - WM_gizmo_group_type_ensure_ptr(gzgt); - } - } - else { - CLOG_WARN(WM_LOG_TOOLS, "'%s' widget not found", idname); - } - } - - if (tref_rt->data_block[0]) { - Main *bmain = CTX_data_main(C); - - if ((tref->space_type == SPACE_VIEW3D) && - (tref->mode == CTX_MODE_SCULPT_GPENCIL)) - { - const EnumPropertyItem *items = rna_enum_gpencil_sculpt_brush_items; - const int i = RNA_enum_from_identifier(items, tref_rt->data_block); - if (i != -1) { - const int value = items[i].value; - wmWindowManager *wm = bmain->wm.first; - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (workspace == WM_window_get_active_workspace(win)) { - Scene *scene = WM_window_get_active_scene(win); - ToolSettings *ts = scene->toolsettings; - ts->gp_sculpt.brushtype = value; - } - } - } - } - else if ((tref->space_type == SPACE_VIEW3D) && - (tref->mode == CTX_MODE_WEIGHT_GPENCIL)) - { - const EnumPropertyItem *items = rna_enum_gpencil_weight_brush_items; - const int i = RNA_enum_from_identifier(items, tref_rt->data_block); - if (i != -1) { - const int value = items[i].value; - wmWindowManager *wm = bmain->wm.first; - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (workspace == WM_window_get_active_workspace(win)) { - Scene *scene = WM_window_get_active_scene(win); - ToolSettings *ts = scene->toolsettings; - ts->gp_sculpt.weighttype = value; - } - } - } - } - else if ((tref->space_type == SPACE_VIEW3D) && - (tref->mode == CTX_MODE_PARTICLE)) - { - const EnumPropertyItem *items = rna_enum_particle_edit_hair_brush_items; - const int i = RNA_enum_from_identifier(items, tref_rt->data_block); - if (i != -1) { - const int value = items[i].value; - wmWindowManager *wm = bmain->wm.first; - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (workspace == WM_window_get_active_workspace(win)) { - Scene *scene = WM_window_get_active_scene(win); - ToolSettings *ts = scene->toolsettings; - ts->particle.brushtype = value; - } - } - } - } - else if ((tref->space_type == SPACE_IMAGE) && - (tref->mode == SI_MODE_UV)) - { - /* Note that switching uv-sculpt boolean is a hack at the moment. - * It would be best to make this either an operator or a higher level mode (like mesh-object sculpt mode). */ - const EnumPropertyItem *items = rna_enum_uv_sculpt_tool_items; - const int i = RNA_enum_from_identifier(items, tref_rt->data_block); - if (i != -1) { - const int value = items[i].value; - wmWindowManager *wm = bmain->wm.first; - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (workspace == WM_window_get_active_workspace(win)) { - Scene *scene = WM_window_get_active_scene(win); - ToolSettings *ts = scene->toolsettings; - ts->uv_sculpt_tool = value; - - if (ts->use_uv_sculpt == false) { - ts->use_uv_sculpt = true; - toolsystem_ref_link__refresh_image_uv_sculpt(C, scene); - } - } - } - } - } - else { - const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref); - BLI_assert(paint_mode != PAINT_MODE_INVALID); - const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); - BLI_assert(items != NULL); - - const int i = items ? RNA_enum_from_identifier(items, tref_rt->data_block) : -1; - if (i != -1) { - const int slot_index = items[i].value; - wmWindowManager *wm = bmain->wm.first; - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (workspace == WM_window_get_active_workspace(win)) { - Scene *scene = WM_window_get_active_scene(win); - Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); - struct Brush *brush = BKE_paint_toolslots_brush_get(paint, slot_index); - if (brush == NULL) { - /* Could make into a function. */ - brush = (struct Brush *)BKE_libblock_find_name(bmain, ID_BR, items[i].name); - if (brush && slot_index == BKE_brush_tool_get(brush, paint)) { - /* pass */ - } - else { - brush = BKE_brush_add(bmain, items[i].name, paint->runtime.ob_mode); - BKE_brush_tool_set(brush, paint, slot_index); - } - BKE_paint_brush_set(paint, brush); - } - BKE_paint_brush_set(paint, brush); - } - } - } - } - } - else { - /* XXX, this part is weak, disables uv_sculpt when non uv-tool set. */ - if ((tref->space_type == SPACE_IMAGE) && - (tref->mode == SI_MODE_UV)) - { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = bmain->wm.first; - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (workspace == WM_window_get_active_workspace(win)) { - Scene *scene = WM_window_get_active_scene(win); - ToolSettings *ts = scene->toolsettings; - if (ts->use_uv_sculpt == true) { - ts->use_uv_sculpt = false; - toolsystem_ref_link__refresh_image_uv_sculpt(C, scene); - } - } - } - } - } + bToolRef_Runtime *tref_rt = tref->runtime; + if (tref_rt->gizmo_group[0]) { + const char *idname = tref_rt->gizmo_group; + wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false); + if (gzgt != NULL) { + if ((gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_INIT) == 0) { + WM_gizmo_group_type_ensure_ptr(gzgt); + } + } + else { + CLOG_WARN(WM_LOG_TOOLS, "'%s' widget not found", idname); + } + } + + if (tref_rt->data_block[0]) { + Main *bmain = CTX_data_main(C); + + if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_SCULPT_GPENCIL)) { + const EnumPropertyItem *items = rna_enum_gpencil_sculpt_brush_items; + const int i = RNA_enum_from_identifier(items, tref_rt->data_block); + if (i != -1) { + const int value = items[i].value; + wmWindowManager *wm = bmain->wm.first; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (workspace == WM_window_get_active_workspace(win)) { + Scene *scene = WM_window_get_active_scene(win); + ToolSettings *ts = scene->toolsettings; + ts->gp_sculpt.brushtype = value; + } + } + } + } + else if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_WEIGHT_GPENCIL)) { + const EnumPropertyItem *items = rna_enum_gpencil_weight_brush_items; + const int i = RNA_enum_from_identifier(items, tref_rt->data_block); + if (i != -1) { + const int value = items[i].value; + wmWindowManager *wm = bmain->wm.first; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (workspace == WM_window_get_active_workspace(win)) { + Scene *scene = WM_window_get_active_scene(win); + ToolSettings *ts = scene->toolsettings; + ts->gp_sculpt.weighttype = value; + } + } + } + } + else if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_PARTICLE)) { + const EnumPropertyItem *items = rna_enum_particle_edit_hair_brush_items; + const int i = RNA_enum_from_identifier(items, tref_rt->data_block); + if (i != -1) { + const int value = items[i].value; + wmWindowManager *wm = bmain->wm.first; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (workspace == WM_window_get_active_workspace(win)) { + Scene *scene = WM_window_get_active_scene(win); + ToolSettings *ts = scene->toolsettings; + ts->particle.brushtype = value; + } + } + } + } + else if ((tref->space_type == SPACE_IMAGE) && (tref->mode == SI_MODE_UV)) { + /* Note that switching uv-sculpt boolean is a hack at the moment. + * It would be best to make this either an operator or a higher level mode (like mesh-object sculpt mode). */ + const EnumPropertyItem *items = rna_enum_uv_sculpt_tool_items; + const int i = RNA_enum_from_identifier(items, tref_rt->data_block); + if (i != -1) { + const int value = items[i].value; + wmWindowManager *wm = bmain->wm.first; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (workspace == WM_window_get_active_workspace(win)) { + Scene *scene = WM_window_get_active_scene(win); + ToolSettings *ts = scene->toolsettings; + ts->uv_sculpt_tool = value; + + if (ts->use_uv_sculpt == false) { + ts->use_uv_sculpt = true; + toolsystem_ref_link__refresh_image_uv_sculpt(C, scene); + } + } + } + } + } + else { + const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref); + BLI_assert(paint_mode != PAINT_MODE_INVALID); + const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); + BLI_assert(items != NULL); + + const int i = items ? RNA_enum_from_identifier(items, tref_rt->data_block) : -1; + if (i != -1) { + const int slot_index = items[i].value; + wmWindowManager *wm = bmain->wm.first; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (workspace == WM_window_get_active_workspace(win)) { + Scene *scene = WM_window_get_active_scene(win); + Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); + struct Brush *brush = BKE_paint_toolslots_brush_get(paint, slot_index); + if (brush == NULL) { + /* Could make into a function. */ + brush = (struct Brush *)BKE_libblock_find_name(bmain, ID_BR, items[i].name); + if (brush && slot_index == BKE_brush_tool_get(brush, paint)) { + /* pass */ + } + else { + brush = BKE_brush_add(bmain, items[i].name, paint->runtime.ob_mode); + BKE_brush_tool_set(brush, paint, slot_index); + } + BKE_paint_brush_set(paint, brush); + } + BKE_paint_brush_set(paint, brush); + } + } + } + } + } + else { + /* XXX, this part is weak, disables uv_sculpt when non uv-tool set. */ + if ((tref->space_type == SPACE_IMAGE) && (tref->mode == SI_MODE_UV)) { + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = bmain->wm.first; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (workspace == WM_window_get_active_workspace(win)) { + Scene *scene = WM_window_get_active_scene(win); + ToolSettings *ts = scene->toolsettings; + if (ts->use_uv_sculpt == true) { + ts->use_uv_sculpt = false; + toolsystem_ref_link__refresh_image_uv_sculpt(C, scene); + } + } + } + } + } } static void toolsystem_refresh_ref(bContext *C, WorkSpace *workspace, bToolRef *tref) { - if (tref->runtime == NULL) { - return; - } - /* currently same operation. */ - toolsystem_ref_link(C, workspace, tref); + if (tref->runtime == NULL) { + return; + } + /* currently same operation. */ + toolsystem_ref_link(C, workspace, tref); } void WM_toolsystem_refresh(bContext *C, WorkSpace *workspace, const bToolKey *tkey) { - bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); - if (tref) { - toolsystem_refresh_ref(C, workspace, tref); - } + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + if (tref) { + toolsystem_refresh_ref(C, workspace, tref); + } } static void toolsystem_reinit_ref(bContext *C, WorkSpace *workspace, bToolRef *tref) { - toolsystem_reinit_with_toolref(C, workspace, tref); + toolsystem_reinit_with_toolref(C, workspace, tref); } void WM_toolsystem_reinit(bContext *C, WorkSpace *workspace, const bToolKey *tkey) { - bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); - if (tref) { - toolsystem_reinit_ref(C, workspace, tref); - } + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + if (tref) { + toolsystem_reinit_ref(C, workspace, tref); + } } /* Operate on all active tools. */ void WM_toolsystem_unlink_all(struct bContext *C, struct WorkSpace *workspace) { - LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { - tref->tag = 0; - } + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + tref->tag = 0; + } - LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { - if (tref->runtime) { - if (tref->tag == 0) { - toolsystem_unlink_ref(C, workspace, tref); - tref->tag = 1; - } - } - } + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + if (tref->runtime) { + if (tref->tag == 0) { + toolsystem_unlink_ref(C, workspace, tref); + tref->tag = 1; + } + } + } } void WM_toolsystem_refresh_all(struct bContext *C, struct WorkSpace *workspace) { - BLI_assert(0); - LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { - toolsystem_refresh_ref(C, workspace, tref); - } + BLI_assert(0); + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + toolsystem_refresh_ref(C, workspace, tref); + } } void WM_toolsystem_reinit_all(struct bContext *C, wmWindow *win) { - bScreen *screen = WM_window_get_active_screen(win); - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - if (((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) { - continue; - } + bScreen *screen = WM_window_get_active_screen(win); + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) { + continue; + } - WorkSpace *workspace = WM_window_get_active_workspace(win); - const bToolKey tkey = { - .space_type = sa->spacetype, - .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), - }; - bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey); - if (tref) { - if (tref->tag == 0) { - toolsystem_reinit_ref(C, workspace, tref); - tref->tag = 1; - } - } - } + WorkSpace *workspace = WM_window_get_active_workspace(win); + const bToolKey tkey = { + .space_type = sa->spacetype, + .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), + }; + bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey); + if (tref) { + if (tref->tag == 0) { + toolsystem_reinit_ref(C, workspace, tref); + tref->tag = 1; + } + } + } } -void WM_toolsystem_ref_set_from_runtime( - struct bContext *C, struct WorkSpace *workspace, bToolRef *tref, - const bToolRef_Runtime *tref_rt, const char *idname) +void WM_toolsystem_ref_set_from_runtime(struct bContext *C, + struct WorkSpace *workspace, + bToolRef *tref, + const bToolRef_Runtime *tref_rt, + const char *idname) { - Main *bmain = CTX_data_main(C); + Main *bmain = CTX_data_main(C); - if (tref->runtime) { - toolsystem_unlink_ref(C, workspace, tref); - } + if (tref->runtime) { + toolsystem_unlink_ref(C, workspace, tref); + } - STRNCPY(tref->idname, idname); + STRNCPY(tref->idname, idname); - /* BAD DESIGN WARNING: used for topbar. */ - workspace->tools_space_type = tref->space_type; - workspace->tools_mode = tref->mode; + /* BAD DESIGN WARNING: used for topbar. */ + workspace->tools_space_type = tref->space_type; + workspace->tools_mode = tref->mode; - if (tref->runtime == NULL) { - tref->runtime = MEM_callocN(sizeof(*tref->runtime), __func__); - } + if (tref->runtime == NULL) { + tref->runtime = MEM_callocN(sizeof(*tref->runtime), __func__); + } - if (tref_rt != tref->runtime) { - *tref->runtime = *tref_rt; - } + if (tref_rt != tref->runtime) { + *tref->runtime = *tref_rt; + } - toolsystem_ref_link(C, workspace, tref); + toolsystem_ref_link(C, workspace, tref); - toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref); + toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref); - { - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - WM_msg_publish_rna_prop( - mbus, &workspace->id, workspace, WorkSpace, tools); - } + { + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + WM_msg_publish_rna_prop(mbus, &workspace->id, workspace, WorkSpace, tools); + } } /** @@ -446,181 +436,167 @@ void WM_toolsystem_ref_set_from_runtime( * * \see #toolsystem_ref_link */ -void WM_toolsystem_ref_sync_from_context( - Main *bmain, WorkSpace *workspace, bToolRef *tref) -{ - bToolRef_Runtime *tref_rt = tref->runtime; - if ((tref_rt == NULL) || (tref_rt->data_block[0] == '\0')) { - return; - } - wmWindowManager *wm = bmain->wm.first; - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (workspace != WM_window_get_active_workspace(win)) { - continue; - } - - Scene *scene = WM_window_get_active_scene(win); - ToolSettings *ts = scene->toolsettings; - const ViewLayer *view_layer = WM_window_get_active_view_layer(win); - const Object *ob = OBACT(view_layer); - if (ob == NULL) { - /* pass */ - } - else if ((tref->space_type == SPACE_VIEW3D) && - (tref->mode == CTX_MODE_SCULPT_GPENCIL)) - { - if (ob->mode & OB_MODE_SCULPT_GPENCIL) { - const EnumPropertyItem *items = rna_enum_gpencil_sculpt_brush_items; - const int i = RNA_enum_from_value(items, ts->gp_sculpt.brushtype); - const EnumPropertyItem *item = &items[i]; - if (!STREQ(tref_rt->data_block, item->identifier)) { - STRNCPY(tref_rt->data_block, item->identifier); - SNPRINTF(tref->idname, "builtin_brush.%s", item->name); - } - } - } - else if ((tref->space_type == SPACE_VIEW3D) && - (tref->mode == CTX_MODE_WEIGHT_GPENCIL)) - { - if (ob->mode & OB_MODE_WEIGHT_GPENCIL) { - const EnumPropertyItem *items = rna_enum_gpencil_weight_brush_items; - const int i = RNA_enum_from_value(items, ts->gp_sculpt.weighttype); - const EnumPropertyItem *item = &items[i]; - if (!STREQ(tref_rt->data_block, item->identifier)) { - STRNCPY(tref_rt->data_block, item->identifier); - SNPRINTF(tref->idname, "builtin_brush.%s", item->name); - } - } - } - else if ((tref->space_type == SPACE_VIEW3D) && - (tref->mode == CTX_MODE_PARTICLE)) - { - if (ob->mode & OB_MODE_PARTICLE_EDIT) { - const EnumPropertyItem *items = rna_enum_particle_edit_hair_brush_items; - const int i = RNA_enum_from_value(items, ts->particle.brushtype); - const EnumPropertyItem *item = &items[i]; - if (!STREQ(tref_rt->data_block, item->identifier)) { - STRNCPY(tref_rt->data_block, item->identifier); - SNPRINTF(tref->idname, "builtin_brush.%s", item->name); - } - } - } - else if ((tref->space_type == SPACE_IMAGE) && - (tref->mode == SI_MODE_UV)) - { - if (ob->mode & OB_MODE_EDIT) { - const EnumPropertyItem *items = rna_enum_uv_sculpt_tool_items; - const int i = RNA_enum_from_value(items, ts->uv_sculpt_tool); - const EnumPropertyItem *item = &items[i]; - if (!STREQ(tref_rt->data_block, item->identifier)) { - STRNCPY(tref_rt->data_block, item->identifier); - SNPRINTF(tref->idname, "builtin_brush.%s", item->name); - } - } - } - else { - const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref); - Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); - const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); - if (paint && paint->brush && items) { - const ID *brush = (ID *)paint->brush; - const char tool_type = BKE_brush_tool_get((struct Brush *)brush, paint); - const int i = RNA_enum_from_value(items, tool_type); - /* Possible when loading files from the future. */ - if (i != -1) { - const char *name = items[i].name; - const char *identifier = items[i].identifier; - if (!STREQ(tref_rt->data_block, identifier)) { - STRNCPY(tref_rt->data_block, identifier); - SNPRINTF(tref->idname, "builtin_brush.%s", name); - } - } - } - } - } +void WM_toolsystem_ref_sync_from_context(Main *bmain, WorkSpace *workspace, bToolRef *tref) +{ + bToolRef_Runtime *tref_rt = tref->runtime; + if ((tref_rt == NULL) || (tref_rt->data_block[0] == '\0')) { + return; + } + wmWindowManager *wm = bmain->wm.first; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (workspace != WM_window_get_active_workspace(win)) { + continue; + } + + Scene *scene = WM_window_get_active_scene(win); + ToolSettings *ts = scene->toolsettings; + const ViewLayer *view_layer = WM_window_get_active_view_layer(win); + const Object *ob = OBACT(view_layer); + if (ob == NULL) { + /* pass */ + } + else if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_SCULPT_GPENCIL)) { + if (ob->mode & OB_MODE_SCULPT_GPENCIL) { + const EnumPropertyItem *items = rna_enum_gpencil_sculpt_brush_items; + const int i = RNA_enum_from_value(items, ts->gp_sculpt.brushtype); + const EnumPropertyItem *item = &items[i]; + if (!STREQ(tref_rt->data_block, item->identifier)) { + STRNCPY(tref_rt->data_block, item->identifier); + SNPRINTF(tref->idname, "builtin_brush.%s", item->name); + } + } + } + else if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_WEIGHT_GPENCIL)) { + if (ob->mode & OB_MODE_WEIGHT_GPENCIL) { + const EnumPropertyItem *items = rna_enum_gpencil_weight_brush_items; + const int i = RNA_enum_from_value(items, ts->gp_sculpt.weighttype); + const EnumPropertyItem *item = &items[i]; + if (!STREQ(tref_rt->data_block, item->identifier)) { + STRNCPY(tref_rt->data_block, item->identifier); + SNPRINTF(tref->idname, "builtin_brush.%s", item->name); + } + } + } + else if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_PARTICLE)) { + if (ob->mode & OB_MODE_PARTICLE_EDIT) { + const EnumPropertyItem *items = rna_enum_particle_edit_hair_brush_items; + const int i = RNA_enum_from_value(items, ts->particle.brushtype); + const EnumPropertyItem *item = &items[i]; + if (!STREQ(tref_rt->data_block, item->identifier)) { + STRNCPY(tref_rt->data_block, item->identifier); + SNPRINTF(tref->idname, "builtin_brush.%s", item->name); + } + } + } + else if ((tref->space_type == SPACE_IMAGE) && (tref->mode == SI_MODE_UV)) { + if (ob->mode & OB_MODE_EDIT) { + const EnumPropertyItem *items = rna_enum_uv_sculpt_tool_items; + const int i = RNA_enum_from_value(items, ts->uv_sculpt_tool); + const EnumPropertyItem *item = &items[i]; + if (!STREQ(tref_rt->data_block, item->identifier)) { + STRNCPY(tref_rt->data_block, item->identifier); + SNPRINTF(tref->idname, "builtin_brush.%s", item->name); + } + } + } + else { + const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref); + Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); + const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); + if (paint && paint->brush && items) { + const ID *brush = (ID *)paint->brush; + const char tool_type = BKE_brush_tool_get((struct Brush *)brush, paint); + const int i = RNA_enum_from_value(items, tool_type); + /* Possible when loading files from the future. */ + if (i != -1) { + const char *name = items[i].name; + const char *identifier = items[i].identifier; + if (!STREQ(tref_rt->data_block, identifier)) { + STRNCPY(tref_rt->data_block, identifier); + SNPRINTF(tref->idname, "builtin_brush.%s", name); + } + } + } + } + } } void WM_toolsystem_init(bContext *C) { - Main *bmain = CTX_data_main(C); + Main *bmain = CTX_data_main(C); - BLI_assert(CTX_wm_window(C) == NULL); + BLI_assert(CTX_wm_window(C) == NULL); - LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) { - LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { - MEM_SAFE_FREE(tref->runtime); - } - } + LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) { + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + MEM_SAFE_FREE(tref->runtime); + } + } - /* Rely on screen initialization for gizmos. */ + /* Rely on screen initialization for gizmos. */ } static bool toolsystem_key_ensure_check(const bToolKey *tkey) { - switch (tkey->space_type) { - case SPACE_VIEW3D: - return true; - case SPACE_IMAGE: - if (ELEM(tkey->mode, SI_MODE_PAINT, SI_MODE_UV)) { - return true; - } - break; - case SPACE_NODE: - return true; - } - return false; -} - -int WM_toolsystem_mode_from_spacetype( - ViewLayer *view_layer, ScrArea *sa, int spacetype) -{ - int mode = -1; - switch (spacetype) { - case SPACE_VIEW3D: - { - /* 'sa' may be NULL in this case. */ - Object *obact = OBACT(view_layer); - if (obact != NULL) { - Object *obedit = OBEDIT_FROM_OBACT(obact); - mode = CTX_data_mode_enum_ex(obedit, obact, obact->mode); - } - else { - mode = CTX_MODE_OBJECT; - } - break; - } - case SPACE_IMAGE: - { - SpaceImage *sima = sa->spacedata.first; - mode = sima->mode; - break; - } - case SPACE_NODE: - { - mode = 0; - break; - } - } - return mode; -} - -bool WM_toolsystem_key_from_context( - ViewLayer *view_layer, ScrArea *sa, bToolKey *tkey) -{ - int space_type = SPACE_EMPTY; - int mode = -1; - - if (sa != NULL) { - space_type = sa->spacetype; - mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, space_type); - } - - if (mode != -1) { - tkey->space_type = space_type; - tkey->mode = mode; - return true; - } - return false; + switch (tkey->space_type) { + case SPACE_VIEW3D: + return true; + case SPACE_IMAGE: + if (ELEM(tkey->mode, SI_MODE_PAINT, SI_MODE_UV)) { + return true; + } + break; + case SPACE_NODE: + return true; + } + return false; +} + +int WM_toolsystem_mode_from_spacetype(ViewLayer *view_layer, ScrArea *sa, int spacetype) +{ + int mode = -1; + switch (spacetype) { + case SPACE_VIEW3D: { + /* 'sa' may be NULL in this case. */ + Object *obact = OBACT(view_layer); + if (obact != NULL) { + Object *obedit = OBEDIT_FROM_OBACT(obact); + mode = CTX_data_mode_enum_ex(obedit, obact, obact->mode); + } + else { + mode = CTX_MODE_OBJECT; + } + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + mode = sima->mode; + break; + } + case SPACE_NODE: { + mode = 0; + break; + } + } + return mode; +} + +bool WM_toolsystem_key_from_context(ViewLayer *view_layer, ScrArea *sa, bToolKey *tkey) +{ + int space_type = SPACE_EMPTY; + int mode = -1; + + if (sa != NULL) { + space_type = sa->spacetype; + mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, space_type); + } + + if (mode != -1) { + tkey->space_type = space_type; + tkey->mode = mode; + return true; + } + return false; } /** @@ -632,315 +608,324 @@ bool WM_toolsystem_key_from_context( */ void WM_toolsystem_refresh_active(bContext *C) { - Main *bmain = CTX_data_main(C); - for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { - WorkSpace *workspace = WM_window_get_active_workspace(win); - bScreen *screen = WM_window_get_active_screen(win); - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - int mode_other = 0; - enum { UNSET = -1, CHANGE = 0, MATCH = 1 } mode_match = UNSET; - /* Could skip loop for modes that don't depend on space type. */ - for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - /* Don't change the space type of the active tool, only update it's mode. */ - if (sa->spacetype == workspace->tools_space_type) { - const int mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype); - if (workspace->tools_mode == mode) { - mode_match = MATCH; - break; - } - else if (mode_match == -1) { - mode_match = CHANGE; - mode_other = mode; - } - } - } - - if (mode_match == CHANGE) { - const bToolKey tkey = { - .space_type = workspace->tools_space_type, - .mode = mode_other, - }; - toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL); - } - } - } + Main *bmain = CTX_data_main(C); + for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { + WorkSpace *workspace = WM_window_get_active_workspace(win); + bScreen *screen = WM_window_get_active_screen(win); + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + int mode_other = 0; + enum { UNSET = -1, CHANGE = 0, MATCH = 1 } mode_match = UNSET; + /* Could skip loop for modes that don't depend on space type. */ + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + /* Don't change the space type of the active tool, only update it's mode. */ + if (sa->spacetype == workspace->tools_space_type) { + const int mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype); + if (workspace->tools_mode == mode) { + mode_match = MATCH; + break; + } + else if (mode_match == -1) { + mode_match = CHANGE; + mode_other = mode; + } + } + } + + if (mode_match == CHANGE) { + const bToolKey tkey = { + .space_type = workspace->tools_space_type, + .mode = mode_other, + }; + toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL); + } + } + } } void WM_toolsystem_refresh_screen_area(WorkSpace *workspace, ViewLayer *view_layer, ScrArea *sa) { - sa->runtime.tool = NULL; - sa->runtime.is_tool_set = true; - const int mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype); - for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) { - if (tref->space_type == sa->spacetype) { - if (tref->mode == mode) { - sa->runtime.tool = tref; - break; - } - } - } + sa->runtime.tool = NULL; + sa->runtime.is_tool_set = true; + const int mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype); + for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) { + if (tref->space_type == sa->spacetype) { + if (tref->mode == mode) { + sa->runtime.tool = tref; + break; + } + } + } } void WM_toolsystem_refresh_screen_all(Main *bmain) { - /* Update all ScrArea's tools */ - for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { - WorkSpace *workspace = WM_window_get_active_workspace(win); - bool space_type_has_tools[SPACE_TYPE_LAST + 1] = {0}; - for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) { - space_type_has_tools[tref->space_type] = true; - } - bScreen *screen = WM_window_get_active_screen(win); - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - sa->runtime.tool = NULL; - sa->runtime.is_tool_set = true; - if (space_type_has_tools[sa->spacetype]) { - WM_toolsystem_refresh_screen_area(workspace, view_layer, sa); - } - } - } - } -} - -static void toolsystem_refresh_screen_from_active_tool( - Main *bmain, WorkSpace *workspace, bToolRef *tref) -{ - /* Update all ScrArea's tools */ - for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (workspace == WM_window_get_active_workspace(win)) { - bScreen *screen = WM_window_get_active_screen(win); - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == tref->space_type) { - int mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype); - if (mode == tref->mode) { - sa->runtime.tool = tref; - sa->runtime.is_tool_set = true; - } - } - } - } - } - } + /* Update all ScrArea's tools */ + for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { + WorkSpace *workspace = WM_window_get_active_workspace(win); + bool space_type_has_tools[SPACE_TYPE_LAST + 1] = {0}; + for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) { + space_type_has_tools[tref->space_type] = true; + } + bScreen *screen = WM_window_get_active_screen(win); + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + sa->runtime.tool = NULL; + sa->runtime.is_tool_set = true; + if (space_type_has_tools[sa->spacetype]) { + WM_toolsystem_refresh_screen_area(workspace, view_layer, sa); + } + } + } + } +} + +static void toolsystem_refresh_screen_from_active_tool(Main *bmain, + WorkSpace *workspace, + bToolRef *tref) +{ + /* Update all ScrArea's tools */ + for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (workspace == WM_window_get_active_workspace(win)) { + bScreen *screen = WM_window_get_active_screen(win); + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == tref->space_type) { + int mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype); + if (mode == tref->mode) { + sa->runtime.tool = tref; + sa->runtime.is_tool_set = true; + } + } + } + } + } + } } bToolRef *WM_toolsystem_ref_set_by_id( - bContext *C, WorkSpace *workspace, const bToolKey *tkey, - const char *name, bool cycle) + bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *name, bool cycle) { - wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_id", false); - /* On startup, Python operatores are not yet loaded. */ - if (ot == NULL) { - return NULL; - } - PointerRNA op_props; - WM_operator_properties_create_ptr(&op_props, ot); - RNA_string_set(&op_props, "name", name); + wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_id", false); + /* On startup, Python operatores are not yet loaded. */ + if (ot == NULL) { + return NULL; + } + PointerRNA op_props; + WM_operator_properties_create_ptr(&op_props, ot); + RNA_string_set(&op_props, "name", name); - /* Will get from context if not set. */ - bToolKey tkey_from_context; - if (tkey == NULL) { - ViewLayer *view_layer = CTX_data_view_layer(C); - ScrArea *sa = CTX_wm_area(C); - WM_toolsystem_key_from_context(view_layer, sa, &tkey_from_context); - tkey = &tkey_from_context; - } + /* Will get from context if not set. */ + bToolKey tkey_from_context; + if (tkey == NULL) { + ViewLayer *view_layer = CTX_data_view_layer(C); + ScrArea *sa = CTX_wm_area(C); + WM_toolsystem_key_from_context(view_layer, sa, &tkey_from_context); + tkey = &tkey_from_context; + } - BLI_assert((1 << tkey->space_type) & WM_TOOLSYSTEM_SPACE_MASK); + BLI_assert((1 << tkey->space_type) & WM_TOOLSYSTEM_SPACE_MASK); - RNA_enum_set(&op_props, "space_type", tkey->space_type); - RNA_boolean_set(&op_props, "cycle", cycle); + RNA_enum_set(&op_props, "space_type", tkey->space_type); + RNA_boolean_set(&op_props, "cycle", cycle); - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props); - WM_operator_properties_free(&op_props); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props); + WM_operator_properties_free(&op_props); - bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); - if (tref) { - Main *bmain = CTX_data_main(C); - toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref); - } + if (tref) { + Main *bmain = CTX_data_main(C); + toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref); + } - return (tref && STREQ(tref->idname, name)) ? tref : NULL; + return (tref && STREQ(tref->idname, name)) ? tref : NULL; } -static void toolsystem_reinit_with_toolref( - bContext *C, WorkSpace *workspace, bToolRef *tref) +static void toolsystem_reinit_with_toolref(bContext *C, WorkSpace *workspace, bToolRef *tref) { - bToolKey tkey = { - .space_type = tref->space_type, - .mode = tref->mode, - }; - WM_toolsystem_ref_set_by_id(C, workspace, &tkey, tref->idname, false); + bToolKey tkey = { + .space_type = tref->space_type, + .mode = tref->mode, + }; + WM_toolsystem_ref_set_by_id(C, workspace, &tkey, tref->idname, false); } static const char *toolsystem_default_tool(const bToolKey *tkey) { - switch (tkey->space_type) { - case SPACE_VIEW3D: - switch (tkey->mode) { - /* Use the names of the enums for each brush tool. */ - case CTX_MODE_SCULPT: - case CTX_MODE_PAINT_VERTEX: - case CTX_MODE_PAINT_WEIGHT: - case CTX_MODE_WEIGHT_GPENCIL: - case CTX_MODE_PAINT_TEXTURE: - case CTX_MODE_PAINT_GPENCIL: - return "builtin_brush.Draw"; - case CTX_MODE_SCULPT_GPENCIL: - return "builtin_brush.Push"; - /* end temporary hack. */ - - case CTX_MODE_PARTICLE: - return "builtin_brush.Comb"; - case CTX_MODE_EDIT_TEXT: - return "builtin.cursor"; - } - break; - case SPACE_IMAGE: - switch (tkey->mode) { - case SI_MODE_PAINT: - return "builtin_brush.draw"; - } - break; - case SPACE_NODE: - { - /* 'Select Box' interferes with cut-links which is handy. */ - return "builtin.select"; - } - } - - return "builtin.select_box"; + switch (tkey->space_type) { + case SPACE_VIEW3D: + switch (tkey->mode) { + /* Use the names of the enums for each brush tool. */ + case CTX_MODE_SCULPT: + case CTX_MODE_PAINT_VERTEX: + case CTX_MODE_PAINT_WEIGHT: + case CTX_MODE_WEIGHT_GPENCIL: + case CTX_MODE_PAINT_TEXTURE: + case CTX_MODE_PAINT_GPENCIL: + return "builtin_brush.Draw"; + case CTX_MODE_SCULPT_GPENCIL: + return "builtin_brush.Push"; + /* end temporary hack. */ + + case CTX_MODE_PARTICLE: + return "builtin_brush.Comb"; + case CTX_MODE_EDIT_TEXT: + return "builtin.cursor"; + } + break; + case SPACE_IMAGE: + switch (tkey->mode) { + case SI_MODE_PAINT: + return "builtin_brush.draw"; + } + break; + case SPACE_NODE: { + /* 'Select Box' interferes with cut-links which is handy. */ + return "builtin.select"; + } + } + + return "builtin.select_box"; } /** * Run after changing modes. */ -static bToolRef *toolsystem_reinit_ensure_toolref( - bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *default_tool) -{ - bToolRef *tref; - if (WM_toolsystem_ref_ensure(workspace, tkey, &tref)) { - if (default_tool == NULL) { - default_tool = toolsystem_default_tool(tkey); - } - STRNCPY(tref->idname, default_tool); - } - toolsystem_reinit_with_toolref(C, workspace, tref); - return tref; +static bToolRef *toolsystem_reinit_ensure_toolref(bContext *C, + WorkSpace *workspace, + const bToolKey *tkey, + const char *default_tool) +{ + bToolRef *tref; + if (WM_toolsystem_ref_ensure(workspace, tkey, &tref)) { + if (default_tool == NULL) { + default_tool = toolsystem_default_tool(tkey); + } + STRNCPY(tref->idname, default_tool); + } + toolsystem_reinit_with_toolref(C, workspace, tref); + return tref; } void WM_toolsystem_update_from_context_view3d(bContext *C) { - WorkSpace *workspace = CTX_wm_workspace(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - int space_type = SPACE_VIEW3D; - const bToolKey tkey = { - .space_type = space_type, - .mode = WM_toolsystem_mode_from_spacetype(view_layer, NULL, space_type), - }; - toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL); + WorkSpace *workspace = CTX_wm_workspace(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + int space_type = SPACE_VIEW3D; + const bToolKey tkey = { + .space_type = space_type, + .mode = WM_toolsystem_mode_from_spacetype(view_layer, NULL, space_type), + }; + toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL); } -void WM_toolsystem_update_from_context( - bContext *C, WorkSpace *workspace, ViewLayer *view_layer, - ScrArea *sa) +void WM_toolsystem_update_from_context(bContext *C, + WorkSpace *workspace, + ViewLayer *view_layer, + ScrArea *sa) { - const bToolKey tkey = { - .space_type = sa->spacetype, - .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), - }; - if (toolsystem_key_ensure_check(&tkey)) { - toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL); - } + const bToolKey tkey = { + .space_type = sa->spacetype, + .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), + }; + if (toolsystem_key_ensure_check(&tkey)) { + toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL); + } } - /** * For paint modes to support non-brush tools. */ bool WM_toolsystem_active_tool_is_brush(const bContext *C) { - bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C); - return tref_rt && (tref_rt->data_block[0] != '\0'); + bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C); + return tref_rt && (tref_rt->data_block[0] != '\0'); } /* Follow wmMsgNotifyFn spec */ -void WM_toolsystem_do_msg_notify_tag_refresh( - bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val) -{ - WorkSpace *workspace = CTX_wm_workspace(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - ScrArea *sa = msg_val->user_data; - int space_type = sa->spacetype; - const bToolKey tkey = { - .space_type = space_type, - .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), - }; - WM_toolsystem_refresh(C, workspace, &tkey); - WM_toolsystem_refresh_screen_area(workspace, view_layer, sa); +void WM_toolsystem_do_msg_notify_tag_refresh(bContext *C, + wmMsgSubscribeKey *UNUSED(msg_key), + wmMsgSubscribeValue *msg_val) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + ScrArea *sa = msg_val->user_data; + int space_type = sa->spacetype; + const bToolKey tkey = { + .space_type = space_type, + .mode = WM_toolsystem_mode_from_spacetype(view_layer, sa, sa->spacetype), + }; + WM_toolsystem_refresh(C, workspace, &tkey); + WM_toolsystem_refresh_screen_area(workspace, view_layer, sa); } IDProperty *WM_toolsystem_ref_properties_ensure_idprops(bToolRef *tref) { - if (tref->properties == NULL) { - IDPropertyTemplate val = {0}; - tref->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); - } - return tref->properties; -} - -bool WM_toolsystem_ref_properties_get_ex(bToolRef *tref, const char *idname, StructRNA *type, PointerRNA *r_ptr) -{ - IDProperty *group = tref->properties; - IDProperty *prop = group ? IDP_GetPropertyFromGroup(group, idname) : NULL; - RNA_pointer_create(NULL, type, prop, r_ptr); - return (prop != NULL); -} - -void WM_toolsystem_ref_properties_ensure_ex(bToolRef *tref, const char *idname, StructRNA *type, PointerRNA *r_ptr) -{ - IDProperty *group = WM_toolsystem_ref_properties_ensure_idprops(tref); - IDProperty *prop = IDP_GetPropertyFromGroup(group, idname); - if (prop == NULL) { - IDPropertyTemplate val = {0}; - prop = IDP_New(IDP_GROUP, &val, "wmGenericProperties"); - STRNCPY(prop->name, idname); - IDP_ReplaceInGroup_ex(group, prop, NULL); - } - else { - BLI_assert(prop->type == IDP_GROUP); - } - - RNA_pointer_create(NULL, type, prop, r_ptr); -} - -void WM_toolsystem_ref_properties_init_for_keymap( - bToolRef *tref, PointerRNA *dst_ptr, PointerRNA *src_ptr, wmOperatorType *ot) -{ - *dst_ptr = *src_ptr; - if (dst_ptr->data) { - dst_ptr->data = IDP_CopyProperty(dst_ptr->data); - } - else { - IDPropertyTemplate val = {0}; - dst_ptr->data = IDP_New(IDP_GROUP, &val, "wmOpItemProp"); - } - if (tref->properties != NULL) { - IDProperty *prop = IDP_GetPropertyFromGroup(tref->properties, ot->idname); - if (prop) { - /* Important key-map items properties don't get overwritten by the tools. - * - When a key-map item doesn't set a property, the tool-systems is used. - * - When it does, it overrides the tool-system. - * - * This way the default action can be to follow the top-bar tool-settings & - * modifier keys can be used to perform different actions that aren't clobbered here. - */ - IDP_MergeGroup(dst_ptr->data, prop, false); - } - } + if (tref->properties == NULL) { + IDPropertyTemplate val = {0}; + tref->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); + } + return tref->properties; +} + +bool WM_toolsystem_ref_properties_get_ex(bToolRef *tref, + const char *idname, + StructRNA *type, + PointerRNA *r_ptr) +{ + IDProperty *group = tref->properties; + IDProperty *prop = group ? IDP_GetPropertyFromGroup(group, idname) : NULL; + RNA_pointer_create(NULL, type, prop, r_ptr); + return (prop != NULL); +} + +void WM_toolsystem_ref_properties_ensure_ex(bToolRef *tref, + const char *idname, + StructRNA *type, + PointerRNA *r_ptr) +{ + IDProperty *group = WM_toolsystem_ref_properties_ensure_idprops(tref); + IDProperty *prop = IDP_GetPropertyFromGroup(group, idname); + if (prop == NULL) { + IDPropertyTemplate val = {0}; + prop = IDP_New(IDP_GROUP, &val, "wmGenericProperties"); + STRNCPY(prop->name, idname); + IDP_ReplaceInGroup_ex(group, prop, NULL); + } + else { + BLI_assert(prop->type == IDP_GROUP); + } + + RNA_pointer_create(NULL, type, prop, r_ptr); +} + +void WM_toolsystem_ref_properties_init_for_keymap(bToolRef *tref, + PointerRNA *dst_ptr, + PointerRNA *src_ptr, + wmOperatorType *ot) +{ + *dst_ptr = *src_ptr; + if (dst_ptr->data) { + dst_ptr->data = IDP_CopyProperty(dst_ptr->data); + } + else { + IDPropertyTemplate val = {0}; + dst_ptr->data = IDP_New(IDP_GROUP, &val, "wmOpItemProp"); + } + if (tref->properties != NULL) { + IDProperty *prop = IDP_GetPropertyFromGroup(tref->properties, ot->idname); + if (prop) { + /* Important key-map items properties don't get overwritten by the tools. + * - When a key-map item doesn't set a property, the tool-systems is used. + * - When it does, it overrides the tool-system. + * + * This way the default action can be to follow the top-bar tool-settings & + * modifier keys can be used to perform different actions that aren't clobbered here. + */ + IDP_MergeGroup(dst_ptr->data, prop, false); + } + } } diff --git a/source/blender/windowmanager/intern/wm_tooltip.c b/source/blender/windowmanager/intern/wm_tooltip.c index 30332f57d8b..fb56b2ef23f 100644 --- a/source/blender/windowmanager/intern/wm_tooltip.c +++ b/source/blender/windowmanager/intern/wm_tooltip.c @@ -38,106 +38,103 @@ static double g_tooltip_time_closed; double WM_tooltip_time_closed(void) { - return g_tooltip_time_closed; + return g_tooltip_time_closed; } -void WM_tooltip_immediate_init( - bContext *C, wmWindow *win, ARegion *ar, - wmTooltipInitFn init) +void WM_tooltip_immediate_init(bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init) { - WM_tooltip_timer_clear(C, win); - - bScreen *screen = WM_window_get_active_screen(win); - if (screen->tool_tip == NULL) { - screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__); - } - screen->tool_tip->region_from = ar; - screen->tool_tip->init = init; - WM_tooltip_init(C, win); + WM_tooltip_timer_clear(C, win); + + bScreen *screen = WM_window_get_active_screen(win); + if (screen->tool_tip == NULL) { + screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__); + } + screen->tool_tip->region_from = ar; + screen->tool_tip->init = init; + WM_tooltip_init(C, win); } void WM_tooltip_timer_init_ex( - bContext *C, wmWindow *win, ARegion *ar, - wmTooltipInitFn init, double delay) + bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init, double delay) { - WM_tooltip_timer_clear(C, win); - - bScreen *screen = WM_window_get_active_screen(win); - wmWindowManager *wm = CTX_wm_manager(C); - if (screen->tool_tip == NULL) { - screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__); - } - screen->tool_tip->region_from = ar; - screen->tool_tip->timer = WM_event_add_timer(wm, win, TIMER, delay); - screen->tool_tip->init = init; + WM_tooltip_timer_clear(C, win); + + bScreen *screen = WM_window_get_active_screen(win); + wmWindowManager *wm = CTX_wm_manager(C); + if (screen->tool_tip == NULL) { + screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__); + } + screen->tool_tip->region_from = ar; + screen->tool_tip->timer = WM_event_add_timer(wm, win, TIMER, delay); + screen->tool_tip->init = init; } -void WM_tooltip_timer_init( - bContext *C, wmWindow *win, ARegion *ar, - wmTooltipInitFn init) +void WM_tooltip_timer_init(bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init) { - WM_tooltip_timer_init_ex(C, win, ar, init, UI_TOOLTIP_DELAY); + WM_tooltip_timer_init_ex(C, win, ar, init, UI_TOOLTIP_DELAY); } void WM_tooltip_timer_clear(bContext *C, wmWindow *win) { - wmWindowManager *wm = CTX_wm_manager(C); - bScreen *screen = WM_window_get_active_screen(win); - if (screen->tool_tip != NULL) { - if (screen->tool_tip->timer != NULL) { - WM_event_remove_timer(wm, win, screen->tool_tip->timer); - screen->tool_tip->timer = NULL; - } - } + wmWindowManager *wm = CTX_wm_manager(C); + bScreen *screen = WM_window_get_active_screen(win); + if (screen->tool_tip != NULL) { + if (screen->tool_tip->timer != NULL) { + WM_event_remove_timer(wm, win, screen->tool_tip->timer); + screen->tool_tip->timer = NULL; + } + } } void WM_tooltip_clear(bContext *C, wmWindow *win) { - WM_tooltip_timer_clear(C, win); - bScreen *screen = WM_window_get_active_screen(win); - if (screen->tool_tip != NULL) { - if (screen->tool_tip->region) { - UI_tooltip_free(C, screen, screen->tool_tip->region); - screen->tool_tip->region = NULL; - g_tooltip_time_closed = PIL_check_seconds_timer(); - } - MEM_freeN(screen->tool_tip); - screen->tool_tip = NULL; - } + WM_tooltip_timer_clear(C, win); + bScreen *screen = WM_window_get_active_screen(win); + if (screen->tool_tip != NULL) { + if (screen->tool_tip->region) { + UI_tooltip_free(C, screen, screen->tool_tip->region); + screen->tool_tip->region = NULL; + g_tooltip_time_closed = PIL_check_seconds_timer(); + } + MEM_freeN(screen->tool_tip); + screen->tool_tip = NULL; + } } void WM_tooltip_init(bContext *C, wmWindow *win) { - WM_tooltip_timer_clear(C, win); - bScreen *screen = WM_window_get_active_screen(win); - if (screen->tool_tip->region) { - UI_tooltip_free(C, screen, screen->tool_tip->region); - screen->tool_tip->region = NULL; - } - const int pass_prev = screen->tool_tip->pass; - double pass_delay = 0.0; - screen->tool_tip->region = screen->tool_tip->init( - C, screen->tool_tip->region_from, - &screen->tool_tip->pass, &pass_delay, &screen->tool_tip->exit_on_event); - if (pass_prev != screen->tool_tip->pass) { - /* The pass changed, add timer for next pass. */ - wmWindowManager *wm = CTX_wm_manager(C); - screen->tool_tip->timer = WM_event_add_timer(wm, win, TIMER, pass_delay); - } - if (screen->tool_tip->region == NULL) { - WM_tooltip_clear(C, win); - } + WM_tooltip_timer_clear(C, win); + bScreen *screen = WM_window_get_active_screen(win); + if (screen->tool_tip->region) { + UI_tooltip_free(C, screen, screen->tool_tip->region); + screen->tool_tip->region = NULL; + } + const int pass_prev = screen->tool_tip->pass; + double pass_delay = 0.0; + screen->tool_tip->region = screen->tool_tip->init(C, + screen->tool_tip->region_from, + &screen->tool_tip->pass, + &pass_delay, + &screen->tool_tip->exit_on_event); + if (pass_prev != screen->tool_tip->pass) { + /* The pass changed, add timer for next pass. */ + wmWindowManager *wm = CTX_wm_manager(C); + screen->tool_tip->timer = WM_event_add_timer(wm, win, TIMER, pass_delay); + } + if (screen->tool_tip->region == NULL) { + WM_tooltip_clear(C, win); + } } void WM_tooltip_refresh(bContext *C, wmWindow *win) { - WM_tooltip_timer_clear(C, win); - bScreen *screen = WM_window_get_active_screen(win); - if (screen->tool_tip != NULL) { - if (screen->tool_tip->region) { - UI_tooltip_free(C, screen, screen->tool_tip->region); - screen->tool_tip->region = NULL; - } - WM_tooltip_init(C, win); - } + WM_tooltip_timer_clear(C, win); + bScreen *screen = WM_window_get_active_screen(win); + if (screen->tool_tip != NULL) { + if (screen->tool_tip->region) { + UI_tooltip_free(C, screen, screen->tool_tip->region); + screen->tool_tip->region = NULL; + } + WM_tooltip_init(C, win); + } } diff --git a/source/blender/windowmanager/intern/wm_uilist_type.c b/source/blender/windowmanager/intern/wm_uilist_type.c index c55f28e2d8d..e79f18eed6f 100644 --- a/source/blender/windowmanager/intern/wm_uilist_type.c +++ b/source/blender/windowmanager/intern/wm_uilist_type.c @@ -38,55 +38,55 @@ static GHash *uilisttypes_hash = NULL; uiListType *WM_uilisttype_find(const char *idname, bool quiet) { - uiListType *ult; + uiListType *ult; - if (idname[0]) { - ult = BLI_ghash_lookup(uilisttypes_hash, idname); - if (ult) { - return ult; - } - } + if (idname[0]) { + ult = BLI_ghash_lookup(uilisttypes_hash, idname); + if (ult) { + return ult; + } + } - if (!quiet) { - printf("search for unknown uilisttype %s\n", idname); - } + if (!quiet) { + printf("search for unknown uilisttype %s\n", idname); + } - return NULL; + return NULL; } bool WM_uilisttype_add(uiListType *ult) { - BLI_ghash_insert(uilisttypes_hash, ult->idname, ult); - return 1; + BLI_ghash_insert(uilisttypes_hash, ult->idname, ult); + return 1; } void WM_uilisttype_freelink(uiListType *ult) { - bool ok; + bool ok; - ok = BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, MEM_freeN); + ok = BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, MEM_freeN); - BLI_assert(ok); - (void)ok; + BLI_assert(ok); + (void)ok; } /* called on initialize WM_init() */ void WM_uilisttype_init(void) { - uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16); + uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16); } void WM_uilisttype_free(void) { - GHashIterator gh_iter; + GHashIterator gh_iter; - GHASH_ITER (gh_iter, uilisttypes_hash) { - uiListType *ult = BLI_ghashIterator_getValue(&gh_iter); - if (ult->ext.free) { - ult->ext.free(ult->ext.data); - } - } + GHASH_ITER (gh_iter, uilisttypes_hash) { + uiListType *ult = BLI_ghashIterator_getValue(&gh_iter); + if (ult->ext.free) { + ult->ext.free(ult->ext.data); + } + } - BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN); - uilisttypes_hash = NULL; + BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN); + uilisttypes_hash = NULL; } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 7994947d943..89696082e7a 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -98,8 +98,8 @@ static GHOST_SystemHandle g_system = NULL; typedef enum eWinOverrideFlag { - WIN_OVERRIDE_GEOM = (1 << 0), - WIN_OVERRIDE_WINSTATE = (1 << 1), + WIN_OVERRIDE_GEOM = (1 << 0), + WIN_OVERRIDE_WINSTATE = (1 << 1), } eWinOverrideFlag; #define GHOST_WINDOW_STATE_DEFAULT GHOST_kWindowStateMaximized @@ -109,19 +109,19 @@ typedef enum eWinOverrideFlag { * These values are typically set by command line arguments. */ static struct WMInitStruct { - /* window geometry */ - int size_x, size_y; - int start_x, start_y; + /* window geometry */ + int size_x, size_y; + int start_x, start_y; - int windowstate; - eWinOverrideFlag override_flag; + int windowstate; + eWinOverrideFlag override_flag; - bool window_focus; - bool native_pixels; + bool window_focus; + bool native_pixels; } wm_init_state = { - .windowstate = GHOST_WINDOW_STATE_DEFAULT, - .window_focus = true, - .native_pixels = true, + .windowstate = GHOST_WINDOW_STATE_DEFAULT, + .window_focus = true, + .native_pixels = true, }; /* ******** win open & close ************ */ @@ -133,218 +133,225 @@ static int wm_window_timer(const bContext *C); * done for Cocoa : returns window contents (and not frame) max size*/ void wm_get_screensize(int *r_width, int *r_height) { - unsigned int uiwidth; - unsigned int uiheight; + unsigned int uiwidth; + unsigned int uiheight; - GHOST_GetMainDisplayDimensions(g_system, &uiwidth, &uiheight); - *r_width = uiwidth; - *r_height = uiheight; + GHOST_GetMainDisplayDimensions(g_system, &uiwidth, &uiheight); + *r_width = uiwidth; + *r_height = uiheight; } /* size of all screens (desktop), useful since the mouse is bound by this */ void wm_get_desktopsize(int *r_width, int *r_height) { - unsigned int uiwidth; - unsigned int uiheight; + unsigned int uiwidth; + unsigned int uiheight; - GHOST_GetAllDisplayDimensions(g_system, &uiwidth, &uiheight); - *r_width = uiwidth; - *r_height = uiheight; + GHOST_GetAllDisplayDimensions(g_system, &uiwidth, &uiheight); + *r_width = uiwidth; + *r_height = uiheight; } /* keeps offset and size within monitor bounds */ /* XXX solve dual screen... */ static void wm_window_check_position(rcti *rect) { - int width, height, d; - - wm_get_screensize(&width, &height); - - if (rect->xmin < 0) { - rect->xmax -= rect->xmin; - rect->xmin = 0; - } - if (rect->ymin < 0) { - rect->ymax -= rect->ymin; - rect->ymin = 0; - } - if (rect->xmax > width) { - d = rect->xmax - width; - rect->xmax -= d; - rect->xmin -= d; - } - if (rect->ymax > height) { - d = rect->ymax - height; - rect->ymax -= d; - rect->ymin -= d; - } - - if (rect->xmin < 0) { - rect->xmin = 0; - } - if (rect->ymin < 0) { - rect->ymin = 0; - } + int width, height, d; + + wm_get_screensize(&width, &height); + + if (rect->xmin < 0) { + rect->xmax -= rect->xmin; + rect->xmin = 0; + } + if (rect->ymin < 0) { + rect->ymax -= rect->ymin; + rect->ymin = 0; + } + if (rect->xmax > width) { + d = rect->xmax - width; + rect->xmax -= d; + rect->xmin -= d; + } + if (rect->ymax > height) { + d = rect->ymax - height; + rect->ymax -= d; + rect->ymin -= d; + } + + if (rect->xmin < 0) { + rect->xmin = 0; + } + if (rect->ymin < 0) { + rect->ymin = 0; + } } static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win) { - if (win->ghostwin) { - /* Prevents non-drawable state of main windows (bugs #22967, - * #25071 and possibly #22477 too). Always clear it even if - * this window was not the drawable one, because we mess with - * drawing context to discard the GW context. */ - wm_window_clear_drawable(wm); + if (win->ghostwin) { + /* Prevents non-drawable state of main windows (bugs #22967, + * #25071 and possibly #22477 too). Always clear it even if + * this window was not the drawable one, because we mess with + * drawing context to discard the GW context. */ + wm_window_clear_drawable(wm); - if (win == wm->winactive) { - wm->winactive = NULL; - } + if (win == wm->winactive) { + wm->winactive = NULL; + } - /* We need this window's opengl context active to discard it. */ - GHOST_ActivateWindowDrawingContext(win->ghostwin); - GPU_context_active_set(win->gpuctx); + /* We need this window's opengl context active to discard it. */ + GHOST_ActivateWindowDrawingContext(win->ghostwin); + GPU_context_active_set(win->gpuctx); - /* Delete local gpu context. */ - GPU_context_discard(win->gpuctx); + /* Delete local gpu context. */ + GPU_context_discard(win->gpuctx); - GHOST_DisposeWindow(g_system, win->ghostwin); - win->ghostwin = NULL; - win->gpuctx = NULL; - } + GHOST_DisposeWindow(g_system, win->ghostwin); + win->ghostwin = NULL; + win->gpuctx = NULL; + } } /* including window itself, C can be NULL. * ED_screen_exit should have been called */ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) { - wmTimer *wt, *wtnext; + wmTimer *wt, *wtnext; - /* update context */ - if (C) { - WM_event_remove_handlers(C, &win->handlers); - WM_event_remove_handlers(C, &win->modalhandlers); + /* update context */ + if (C) { + WM_event_remove_handlers(C, &win->handlers); + WM_event_remove_handlers(C, &win->modalhandlers); - if (CTX_wm_window(C) == win) { - CTX_wm_window_set(C, NULL); - } - } + if (CTX_wm_window(C) == win) { + CTX_wm_window_set(C, NULL); + } + } - BKE_screen_area_map_free(&win->global_areas); + BKE_screen_area_map_free(&win->global_areas); - /* end running jobs, a job end also removes its timer */ - for (wt = wm->timers.first; wt; wt = wtnext) { - wtnext = wt->next; - if (wt->win == win && wt->event_type == TIMERJOBS) { - wm_jobs_timer_ended(wm, wt); - } - } + /* end running jobs, a job end also removes its timer */ + for (wt = wm->timers.first; wt; wt = wtnext) { + wtnext = wt->next; + if (wt->win == win && wt->event_type == TIMERJOBS) { + wm_jobs_timer_ended(wm, wt); + } + } - /* timer removing, need to call this api function */ - for (wt = wm->timers.first; wt; wt = wtnext) { - wtnext = wt->next; - if (wt->win == win) { - WM_event_remove_timer(wm, win, wt); - } - } + /* timer removing, need to call this api function */ + for (wt = wm->timers.first; wt; wt = wtnext) { + wtnext = wt->next; + if (wt->win == win) { + WM_event_remove_timer(wm, win, wt); + } + } - if (win->eventstate) { - MEM_freeN(win->eventstate); - } + if (win->eventstate) { + MEM_freeN(win->eventstate); + } - if (win->cursor_keymap_status) { - MEM_freeN(win->cursor_keymap_status); - } + if (win->cursor_keymap_status) { + MEM_freeN(win->cursor_keymap_status); + } - wm_event_free_all(win); + wm_event_free_all(win); - wm_ghostwindow_destroy(wm, win); + wm_ghostwindow_destroy(wm, win); - BKE_workspace_instance_hook_free(G_MAIN, win->workspace_hook); - MEM_freeN(win->stereo3d_format); + BKE_workspace_instance_hook_free(G_MAIN, win->workspace_hook); + MEM_freeN(win->stereo3d_format); - MEM_freeN(win); + MEM_freeN(win); } static int find_free_winid(wmWindowManager *wm) { - wmWindow *win; - int id = 1; + wmWindow *win; + int id = 1; - for (win = wm->windows.first; win; win = win->next) { - if (id <= win->winid) { - id = win->winid + 1; - } - } - return id; + for (win = wm->windows.first; win; win = win->next) { + if (id <= win->winid) { + id = win->winid + 1; + } + } + return id; } /* don't change context itself */ wmWindow *wm_window_new(bContext *C, wmWindow *parent) { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = MEM_callocN(sizeof(wmWindow), "window"); + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = MEM_callocN(sizeof(wmWindow), "window"); - BLI_addtail(&wm->windows, win); - win->winid = find_free_winid(wm); + BLI_addtail(&wm->windows, win); + win->winid = find_free_winid(wm); - win->parent = (parent && parent->parent) ? parent->parent : parent; - win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)"); - win->workspace_hook = BKE_workspace_instance_hook_create(bmain); + win->parent = (parent && parent->parent) ? parent->parent : parent; + win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)"); + win->workspace_hook = BKE_workspace_instance_hook_create(bmain); - return win; + return win; } /* part of wm_window.c api */ -wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_layout, const bool child) +wmWindow *wm_window_copy(bContext *C, + wmWindow *win_src, + const bool duplicate_layout, + const bool child) { - Main *bmain = CTX_data_main(C); - wmWindow *win_parent = (child) ? win_src : win_src->parent; - wmWindow *win_dst = wm_window_new(C, win_parent); - WorkSpace *workspace = WM_window_get_active_workspace(win_src); - WorkSpaceLayout *layout_old = WM_window_get_active_layout(win_src); - WorkSpaceLayout *layout_new; + Main *bmain = CTX_data_main(C); + wmWindow *win_parent = (child) ? win_src : win_src->parent; + wmWindow *win_dst = wm_window_new(C, win_parent); + WorkSpace *workspace = WM_window_get_active_workspace(win_src); + WorkSpaceLayout *layout_old = WM_window_get_active_layout(win_src); + WorkSpaceLayout *layout_new; - win_dst->posx = win_src->posx + 10; - win_dst->posy = win_src->posy; - win_dst->sizex = win_src->sizex; - win_dst->sizey = win_src->sizey; + win_dst->posx = win_src->posx + 10; + win_dst->posy = win_src->posy; + win_dst->sizex = win_src->sizex; + win_dst->sizey = win_src->sizey; - win_dst->scene = win_src->scene; - STRNCPY(win_dst->view_layer_name, win_src->view_layer_name); - BKE_workspace_active_set(win_dst->workspace_hook, workspace); - layout_new = duplicate_layout ? ED_workspace_layout_duplicate(bmain, workspace, layout_old, win_dst) : layout_old; - BKE_workspace_hook_layout_for_workspace_set(win_dst->workspace_hook, workspace, layout_new); + win_dst->scene = win_src->scene; + STRNCPY(win_dst->view_layer_name, win_src->view_layer_name); + BKE_workspace_active_set(win_dst->workspace_hook, workspace); + layout_new = duplicate_layout ? + ED_workspace_layout_duplicate(bmain, workspace, layout_old, win_dst) : + layout_old; + BKE_workspace_hook_layout_for_workspace_set(win_dst->workspace_hook, workspace, layout_new); - *win_dst->stereo3d_format = *win_src->stereo3d_format; + *win_dst->stereo3d_format = *win_src->stereo3d_format; - return win_dst; + return win_dst; } /** * A higher level version of copy that tests the new window can be added. * (called from the operator directly) */ -wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplicate_layout, const bool child) +wmWindow *wm_window_copy_test(bContext *C, + wmWindow *win_src, + const bool duplicate_layout, + const bool child) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win_dst; + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win_dst; - win_dst = wm_window_copy(C, win_src, duplicate_layout, child); + win_dst = wm_window_copy(C, win_src, duplicate_layout, child); - WM_check(C); + WM_check(C); - if (win_dst->ghostwin) { - WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL); - return win_dst; - } - else { - wm_window_close(C, wm, win_dst); - return NULL; - } + if (win_dst->ghostwin) { + WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL); + return win_dst; + } + else { + wm_window_close(C, wm, win_dst); + return NULL; + } } - /* -------------------------------------------------------------------- */ /** \name Quit Confirmation Dialog * \{ */ @@ -352,121 +359,164 @@ wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplica /** Cancel quitting and close the dialog */ static void wm_block_confirm_quit_cancel(bContext *C, void *arg_block, void *UNUSED(arg)) { - wmWindow *win = CTX_wm_window(C); - UI_popup_block_close(C, win, arg_block); + wmWindow *win = CTX_wm_window(C); + UI_popup_block_close(C, win, arg_block); } /** Discard the file changes and quit */ static void wm_block_confirm_quit_discard(bContext *C, void *arg_block, void *UNUSED(arg)) { - wmWindow *win = CTX_wm_window(C); - UI_popup_block_close(C, win, arg_block); - WM_exit(C); + wmWindow *win = CTX_wm_window(C); + UI_popup_block_close(C, win, arg_block); + WM_exit(C); } /* Save changes and quit */ static void wm_block_confirm_quit_save(bContext *C, void *arg_block, void *UNUSED(arg)) { - PointerRNA props_ptr; - wmWindow *win = CTX_wm_window(C); + PointerRNA props_ptr; + wmWindow *win = CTX_wm_window(C); - UI_popup_block_close(C, win, arg_block); + UI_popup_block_close(C, win, arg_block); - wmOperatorType *ot = WM_operatortype_find("WM_OT_save_mainfile", false); + wmOperatorType *ot = WM_operatortype_find("WM_OT_save_mainfile", false); - WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "exit", true); - /* No need for second confirmation popup. */ - RNA_boolean_set(&props_ptr, "check_existing", false); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); - WM_operator_properties_free(&props_ptr); + WM_operator_properties_create_ptr(&props_ptr, ot); + RNA_boolean_set(&props_ptr, "exit", true); + /* No need for second confirmation popup. */ + RNA_boolean_set(&props_ptr, "check_existing", false); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); } - /* Build the confirm dialog UI */ -static uiBlock *block_create_confirm_quit(struct bContext *C, struct ARegion *ar, void *UNUSED(arg1)) -{ - Main *bmain = CTX_data_main(C); - - uiStyle *style = UI_style_get(); - uiBlock *block = UI_block_begin(C, ar, "confirm_quit_popup", UI_EMBOSS); - - UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); - UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); - UI_block_emboss_set(block, UI_EMBOSS); - - uiLayout *layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.widget_unit * 24, U.widget_unit * 6, 0, style); - - /* Text and some vertical space */ - { - char *message; - if (BKE_main_blendfile_path(bmain)[0] == '\0') { - message = BLI_strdup(IFACE_("This file has not been saved yet. Save before closing?")); - } - else { - const char *basename = BLI_path_basename(BKE_main_blendfile_path(bmain)); - message = BLI_sprintfN(IFACE_("Save changes to \"%s\" before closing?"), basename); - } - uiItemL(layout, message, ICON_ERROR); - MEM_freeN(message); - } - - uiItemS(layout); - uiItemS(layout); - - - /* Buttons */ - uiBut *but; - - uiLayout *split = uiLayoutSplit(layout, 0.0f, true); - - uiLayout *col = uiLayoutColumn(split, false); - - but = uiDefIconTextBut( - block, UI_BTYPE_BUT, 0, ICON_SCREEN_BACK, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Do not quit")); - UI_but_func_set(but, wm_block_confirm_quit_cancel, block, NULL); - - /* empty space between buttons */ - col = uiLayoutColumn(split, false); - uiItemS(col); - - col = uiLayoutColumn(split, 1); - but = uiDefIconTextBut( - block, UI_BTYPE_BUT, 0, ICON_CANCEL, IFACE_("Discard Changes"), 0, 0, 50, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Discard changes and quit")); - UI_but_func_set(but, wm_block_confirm_quit_discard, block, NULL); - - col = uiLayoutColumn(split, 1); - but = uiDefIconTextBut( - block, UI_BTYPE_BUT, 0, ICON_FILE_TICK, IFACE_("Save & Quit"), 0, 0, 50, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Save and quit")); - UI_but_func_set(but, wm_block_confirm_quit_save, block, NULL); - UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT); - - UI_block_bounds_set_centered(block, 10); - - return block; +static uiBlock *block_create_confirm_quit(struct bContext *C, + struct ARegion *ar, + void *UNUSED(arg1)) +{ + Main *bmain = CTX_data_main(C); + + uiStyle *style = UI_style_get(); + uiBlock *block = UI_block_begin(C, ar, "confirm_quit_popup", UI_EMBOSS); + + UI_block_flag_enable( + block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); + UI_block_emboss_set(block, UI_EMBOSS); + + uiLayout *layout = UI_block_layout(block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + 10, + 2, + U.widget_unit * 24, + U.widget_unit * 6, + 0, + style); + + /* Text and some vertical space */ + { + char *message; + if (BKE_main_blendfile_path(bmain)[0] == '\0') { + message = BLI_strdup(IFACE_("This file has not been saved yet. Save before closing?")); + } + else { + const char *basename = BLI_path_basename(BKE_main_blendfile_path(bmain)); + message = BLI_sprintfN(IFACE_("Save changes to \"%s\" before closing?"), basename); + } + uiItemL(layout, message, ICON_ERROR); + MEM_freeN(message); + } + + uiItemS(layout); + uiItemS(layout); + + /* Buttons */ + uiBut *but; + + uiLayout *split = uiLayoutSplit(layout, 0.0f, true); + + uiLayout *col = uiLayoutColumn(split, false); + + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_SCREEN_BACK, + IFACE_("Cancel"), + 0, + 0, + 0, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Do not quit")); + UI_but_func_set(but, wm_block_confirm_quit_cancel, block, NULL); + + /* empty space between buttons */ + col = uiLayoutColumn(split, false); + uiItemS(col); + + col = uiLayoutColumn(split, 1); + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_CANCEL, + IFACE_("Discard Changes"), + 0, + 0, + 50, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Discard changes and quit")); + UI_but_func_set(but, wm_block_confirm_quit_discard, block, NULL); + + col = uiLayoutColumn(split, 1); + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_FILE_TICK, + IFACE_("Save & Quit"), + 0, + 0, + 50, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Save and quit")); + UI_but_func_set(but, wm_block_confirm_quit_save, block, NULL); + UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT); + + UI_block_bounds_set_centered(block, 10); + + return block; } - /** * Call the confirm dialog on quitting. It's displayed in the context window so * caller should set it as desired. */ static void wm_confirm_quit(bContext *C) { - wmWindow *win = CTX_wm_window(C); + wmWindow *win = CTX_wm_window(C); - if (GHOST_SupportsNativeDialogs() == 0) { - if (!UI_popup_block_name_exists(C, "confirm_quit_popup")) { - UI_popup_block_invoke(C, block_create_confirm_quit, NULL); - } - } - else if (GHOST_confirmQuit(win->ghostwin)) { - wm_exit_schedule_delayed(C); - } + if (GHOST_SupportsNativeDialogs() == 0) { + if (!UI_popup_block_name_exists(C, "confirm_quit_popup")) { + UI_popup_block_invoke(C, block_create_confirm_quit, NULL); + } + } + else if (GHOST_confirmQuit(win->ghostwin)) { + wm_exit_schedule_delayed(C); + } } /** @@ -478,26 +528,26 @@ static void wm_confirm_quit(bContext *C) */ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win_ctx = CTX_wm_window(C); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win_ctx = CTX_wm_window(C); - /* The popup will be displayed in the context window which may not be set - * here (this function gets called outside of normal event handling loop). */ - CTX_wm_window_set(C, win); + /* The popup will be displayed in the context window which may not be set + * here (this function gets called outside of normal event handling loop). */ + CTX_wm_window_set(C, win); - if (U.uiflag & USER_SAVE_PROMPT) { - if (!wm->file_saved && !G.background) { - wm_confirm_quit(C); - } - else { - wm_exit_schedule_delayed(C); - } - } - else { - wm_exit_schedule_delayed(C); - } + if (U.uiflag & USER_SAVE_PROMPT) { + if (!wm->file_saved && !G.background) { + wm_confirm_quit(C); + } + else { + wm_exit_schedule_delayed(C); + } + } + else { + wm_exit_schedule_delayed(C); + } - CTX_wm_window_set(C, win_ctx); + CTX_wm_window_set(C, win_ctx); } /** \} */ @@ -505,225 +555,228 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) /* this is event from ghost, or exit-blender op */ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) { - /* First check if there is another main window remaining. */ - wmWindow *win_other; - for (win_other = wm->windows.first; win_other; win_other = win_other->next) { - if (win_other != win && - win_other->parent == NULL && - !WM_window_is_temp_screen(win_other)) - { - break; - } - } + /* First check if there is another main window remaining. */ + wmWindow *win_other; + for (win_other = wm->windows.first; win_other; win_other = win_other->next) { + if (win_other != win && win_other->parent == NULL && !WM_window_is_temp_screen(win_other)) { + break; + } + } - if (win->parent == NULL && win_other == NULL) { - wm_quit_with_optional_confirmation_prompt(C, win); - return; - } + if (win->parent == NULL && win_other == NULL) { + wm_quit_with_optional_confirmation_prompt(C, win); + return; + } - /* close child windows */ - for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { - if (win_child->parent == win) { - wm_window_close(C, wm, win_child); - } - } + /* close child windows */ + for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { + if (win_child->parent == win) { + wm_window_close(C, wm, win_child); + } + } - bScreen *screen = WM_window_get_active_screen(win); - WorkSpace *workspace = WM_window_get_active_workspace(win); - WorkSpaceLayout *layout = BKE_workspace_active_layout_get(win->workspace_hook); + bScreen *screen = WM_window_get_active_screen(win); + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout = BKE_workspace_active_layout_get(win->workspace_hook); - BLI_remlink(&wm->windows, win); + BLI_remlink(&wm->windows, win); - CTX_wm_window_set(C, win); /* needed by handlers */ - WM_event_remove_handlers(C, &win->handlers); - WM_event_remove_handlers(C, &win->modalhandlers); + CTX_wm_window_set(C, win); /* needed by handlers */ + WM_event_remove_handlers(C, &win->handlers); + WM_event_remove_handlers(C, &win->modalhandlers); - /* for regular use this will _never_ be NULL, - * however we may be freeing an improperly initialized window. */ - if (screen) { - ED_screen_exit(C, win, screen); - } + /* for regular use this will _never_ be NULL, + * however we may be freeing an improperly initialized window. */ + if (screen) { + ED_screen_exit(C, win, screen); + } - wm_window_free(C, wm, win); + wm_window_free(C, wm, win); - /* if temp screen, delete it after window free (it stops jobs that can access it) */ - if (screen && screen->temp) { - Main *bmain = CTX_data_main(C); + /* if temp screen, delete it after window free (it stops jobs that can access it) */ + if (screen && screen->temp) { + Main *bmain = CTX_data_main(C); - BLI_assert(BKE_workspace_layout_screen_get(layout) == screen); - BKE_workspace_layout_remove(bmain, workspace, layout); - } + BLI_assert(BKE_workspace_layout_screen_get(layout) == screen); + BKE_workspace_layout_remove(bmain, workspace, layout); + } } void wm_window_title(wmWindowManager *wm, wmWindow *win) { - if (WM_window_is_temp_screen(win)) { - /* nothing to do for 'temp' windows, - * because WM_window_open_temp always sets window title */ - } - else if (win->ghostwin) { - /* this is set to 1 if you don't have startup.blend open */ - if (G.save_over && BKE_main_blendfile_path_from_global()[0]) { - char str[sizeof(((Main *)NULL)->name) + 24]; - BLI_snprintf(str, sizeof(str), "Blender%s [%s%s]", wm->file_saved ? "" : "*", - BKE_main_blendfile_path_from_global(), - G_MAIN->recovered ? " (Recovered)" : ""); - GHOST_SetTitle(win->ghostwin, str); - } - else { - GHOST_SetTitle(win->ghostwin, "Blender"); - } - - /* Informs GHOST of unsaved changes, to set window modified visual indicator (MAC OS X) - * and to give hint of unsaved changes for a user warning mechanism - * in case of OS application terminate request (e.g. OS Shortcut Alt+F4, Cmd+Q, (...), or session end) */ - GHOST_SetWindowModifiedState(win->ghostwin, (GHOST_TUns8) !wm->file_saved); - - } + if (WM_window_is_temp_screen(win)) { + /* nothing to do for 'temp' windows, + * because WM_window_open_temp always sets window title */ + } + else if (win->ghostwin) { + /* this is set to 1 if you don't have startup.blend open */ + if (G.save_over && BKE_main_blendfile_path_from_global()[0]) { + char str[sizeof(((Main *)NULL)->name) + 24]; + BLI_snprintf(str, + sizeof(str), + "Blender%s [%s%s]", + wm->file_saved ? "" : "*", + BKE_main_blendfile_path_from_global(), + G_MAIN->recovered ? " (Recovered)" : ""); + GHOST_SetTitle(win->ghostwin, str); + } + else { + GHOST_SetTitle(win->ghostwin, "Blender"); + } + + /* Informs GHOST of unsaved changes, to set window modified visual indicator (MAC OS X) + * and to give hint of unsaved changes for a user warning mechanism + * in case of OS application terminate request (e.g. OS Shortcut Alt+F4, Cmd+Q, (...), or session end) */ + GHOST_SetWindowModifiedState(win->ghostwin, (GHOST_TUns8)!wm->file_saved); + } } void WM_window_set_dpi(wmWindow *win) { - float auto_dpi = GHOST_GetDPIHint(win->ghostwin); + float auto_dpi = GHOST_GetDPIHint(win->ghostwin); - /* Clamp auto DPI to 96, since our font/interface drawing does not work well - * with lower sizes. The main case we are interested in supporting is higher - * DPI. If a smaller UI is desired it is still possible to adjust UI scale. */ - auto_dpi = max_ff(auto_dpi, 96.0f); + /* Clamp auto DPI to 96, since our font/interface drawing does not work well + * with lower sizes. The main case we are interested in supporting is higher + * DPI. If a smaller UI is desired it is still possible to adjust UI scale. */ + auto_dpi = max_ff(auto_dpi, 96.0f); - /* Lazily init UI scale size, preserving backwards compatibility by - * computing UI scale from ratio of previous DPI and auto DPI */ - if (U.ui_scale == 0) { - int virtual_pixel = (U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1 : 2; + /* Lazily init UI scale size, preserving backwards compatibility by + * computing UI scale from ratio of previous DPI and auto DPI */ + if (U.ui_scale == 0) { + int virtual_pixel = (U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1 : 2; - if (U.dpi == 0) { - U.ui_scale = virtual_pixel; - } - else { - U.ui_scale = (virtual_pixel * U.dpi * 96.0f) / (auto_dpi * 72.0f); - } + if (U.dpi == 0) { + U.ui_scale = virtual_pixel; + } + else { + U.ui_scale = (virtual_pixel * U.dpi * 96.0f) / (auto_dpi * 72.0f); + } - CLAMP(U.ui_scale, 0.25f, 4.0f); - } + CLAMP(U.ui_scale, 0.25f, 4.0f); + } - /* Blender's UI drawing assumes DPI 72 as a good default following macOS - * while Windows and Linux use DPI 96. GHOST assumes a default 96 so we - * remap the DPI to Blender's convention. */ - auto_dpi *= GHOST_GetNativePixelSize(win->ghostwin); - int dpi = auto_dpi * U.ui_scale * (72.0 / 96.0f); + /* Blender's UI drawing assumes DPI 72 as a good default following macOS + * while Windows and Linux use DPI 96. GHOST assumes a default 96 so we + * remap the DPI to Blender's convention. */ + auto_dpi *= GHOST_GetNativePixelSize(win->ghostwin); + int dpi = auto_dpi * U.ui_scale * (72.0 / 96.0f); - /* Automatically set larger pixel size for high DPI. */ - int pixelsize = max_ii(1, (int)(dpi / 64)); - /* User adjustment for pixel size. */ - pixelsize = max_ii(1, pixelsize + U.ui_line_width); + /* Automatically set larger pixel size for high DPI. */ + int pixelsize = max_ii(1, (int)(dpi / 64)); + /* User adjustment for pixel size. */ + pixelsize = max_ii(1, pixelsize + U.ui_line_width); - /* Set user preferences globals for drawing, and for forward compatibility. */ - U.pixelsize = pixelsize; - U.dpi = dpi / pixelsize; - U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE; - U.dpi_fac = ((U.pixelsize * (float)U.dpi) / 72.0f); + /* Set user preferences globals for drawing, and for forward compatibility. */ + U.pixelsize = pixelsize; + U.dpi = dpi / pixelsize; + U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE; + U.dpi_fac = ((U.pixelsize * (float)U.dpi) / 72.0f); - /* Set user preferences globals for drawing, and for forward compatibility. */ - U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72; - /* If line thickness differs from scaling factor then adjustments need to be made */ - U.widget_unit += 2 * ((int)U.pixelsize - (int)U.dpi_fac); + /* Set user preferences globals for drawing, and for forward compatibility. */ + U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72; + /* If line thickness differs from scaling factor then adjustments need to be made */ + U.widget_unit += 2 * ((int)U.pixelsize - (int)U.dpi_fac); - /* update font drawing */ - BLF_default_dpi(U.pixelsize * U.dpi); + /* update font drawing */ + BLF_default_dpi(U.pixelsize * U.dpi); } static void wm_window_ensure_eventstate(wmWindow *win) { - if (win->eventstate) { - return; - } + if (win->eventstate) { + return; + } - win->eventstate = MEM_callocN(sizeof(wmEvent), "window event state"); - wm_get_cursor_position(win, &win->eventstate->x, &win->eventstate->y); + win->eventstate = MEM_callocN(sizeof(wmEvent), "window event state"); + wm_get_cursor_position(win, &win->eventstate->x, &win->eventstate->y); } /* belongs to below */ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wmWindow *win) { - GHOST_WindowHandle ghostwin; - GHOST_GLSettings glSettings = {0}; - int scr_w, scr_h, posy; + GHOST_WindowHandle ghostwin; + GHOST_GLSettings glSettings = {0}; + int scr_w, scr_h, posy; - /* a new window is created when pageflip mode is required for a window */ - if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { - glSettings.flags |= GHOST_glStereoVisual; - } + /* a new window is created when pageflip mode is required for a window */ + if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + glSettings.flags |= GHOST_glStereoVisual; + } - if (G.debug & G_DEBUG_GPU) { - glSettings.flags |= GHOST_glDebugContext; - } + if (G.debug & G_DEBUG_GPU) { + glSettings.flags |= GHOST_glDebugContext; + } - wm_get_screensize(&scr_w, &scr_h); - posy = (scr_h - win->posy - win->sizey); + wm_get_screensize(&scr_w, &scr_h); + posy = (scr_h - win->posy - win->sizey); - /* Clear drawable so we can set the new window. */ - wmWindow *prev_windrawable = wm->windrawable; - wm_window_clear_drawable(wm); + /* Clear drawable so we can set the new window. */ + wmWindow *prev_windrawable = wm->windrawable; + wm_window_clear_drawable(wm); - ghostwin = GHOST_CreateWindow(g_system, title, - win->posx, posy, win->sizex, win->sizey, - (GHOST_TWindowState)win->windowstate, - GHOST_kDrawingContextTypeOpenGL, - glSettings); + ghostwin = GHOST_CreateWindow(g_system, + title, + win->posx, + posy, + win->sizex, + win->sizey, + (GHOST_TWindowState)win->windowstate, + GHOST_kDrawingContextTypeOpenGL, + glSettings); - if (ghostwin) { - GHOST_RectangleHandle bounds; + if (ghostwin) { + GHOST_RectangleHandle bounds; - win->gpuctx = GPU_context_create(); + win->gpuctx = GPU_context_create(); - /* needed so we can detect the graphics card below */ - GPU_init(); + /* needed so we can detect the graphics card below */ + GPU_init(); - /* Set window as drawable upon creation. Note this has already been - * it has already been activated by GHOST_CreateWindow. */ - wm_window_set_drawable(wm, win, false); + /* Set window as drawable upon creation. Note this has already been + * it has already been activated by GHOST_CreateWindow. */ + wm_window_set_drawable(wm, win, false); - win->ghostwin = ghostwin; - GHOST_SetWindowUserData(ghostwin, win); /* pointer back */ + win->ghostwin = ghostwin; + GHOST_SetWindowUserData(ghostwin, win); /* pointer back */ - wm_window_ensure_eventstate(win); + wm_window_ensure_eventstate(win); - /* store actual window size in blender window */ - bounds = GHOST_GetClientBounds(win->ghostwin); + /* store actual window size in blender window */ + bounds = GHOST_GetClientBounds(win->ghostwin); - /* win32: gives undefined window size when minimized */ - if (GHOST_GetWindowState(win->ghostwin) != GHOST_kWindowStateMinimized) { - win->sizex = GHOST_GetWidthRectangle(bounds); - win->sizey = GHOST_GetHeightRectangle(bounds); - } - GHOST_DisposeRectangle(bounds); + /* win32: gives undefined window size when minimized */ + if (GHOST_GetWindowState(win->ghostwin) != GHOST_kWindowStateMinimized) { + win->sizex = GHOST_GetWidthRectangle(bounds); + win->sizey = GHOST_GetHeightRectangle(bounds); + } + GHOST_DisposeRectangle(bounds); #ifndef __APPLE__ - /* set the state here, so minimized state comes up correct on windows */ - if (wm_init_state.window_focus) { - GHOST_SetWindowState(ghostwin, (GHOST_TWindowState)win->windowstate); - } + /* set the state here, so minimized state comes up correct on windows */ + if (wm_init_state.window_focus) { + GHOST_SetWindowState(ghostwin, (GHOST_TWindowState)win->windowstate); + } #endif - /* until screens get drawn, make it nice gray */ - glClearColor(0.55, 0.55, 0.55, 0.0); - /* Crash on OSS ATI: bugs.launchpad.net/ubuntu/+source/mesa/+bug/656100 */ - if (!GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) { - glClear(GL_COLOR_BUFFER_BIT); - } + /* until screens get drawn, make it nice gray */ + glClearColor(0.55, 0.55, 0.55, 0.0); + /* Crash on OSS ATI: bugs.launchpad.net/ubuntu/+source/mesa/+bug/656100 */ + if (!GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) { + glClear(GL_COLOR_BUFFER_BIT); + } - /* needed here, because it's used before it reads userdef */ - WM_window_set_dpi(win); + /* needed here, because it's used before it reads userdef */ + WM_window_set_dpi(win); - wm_window_swap_buffers(win); + wm_window_swap_buffers(win); - //GHOST_SetWindowState(ghostwin, GHOST_kWindowStateModified); + //GHOST_SetWindowState(ghostwin, GHOST_kWindowStateModified); - /* standard state vars for window */ - GPU_state_init(); - } - else { - wm_window_set_drawable(wm, prev_windrawable, false); - } + /* standard state vars for window */ + GPU_state_init(); + } + else { + wm_window_set_drawable(wm, prev_windrawable, false); + } } /** @@ -741,90 +794,90 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm */ void wm_window_ghostwindows_ensure(wmWindowManager *wm) { - wmKeyMap *keymap; - wmWindow *win; + wmKeyMap *keymap; + wmWindow *win; - BLI_assert(G.background == false); + BLI_assert(G.background == false); - /* no commandline prefsize? then we set this. - * Note that these values will be used only - * when there is no startup.blend yet. - */ - if (wm_init_state.size_x == 0) { - wm_get_screensize(&wm_init_state.size_x, &wm_init_state.size_y); + /* no commandline prefsize? then we set this. + * Note that these values will be used only + * when there is no startup.blend yet. + */ + if (wm_init_state.size_x == 0) { + wm_get_screensize(&wm_init_state.size_x, &wm_init_state.size_y); - /* note!, this isnt quite correct, active screen maybe offset 1000s if PX, - * we'd need a wm_get_screensize like function that gives offset, - * in practice the window manager will likely move to the correct monitor */ - wm_init_state.start_x = 0; - wm_init_state.start_y = 0; + /* note!, this isnt quite correct, active screen maybe offset 1000s if PX, + * we'd need a wm_get_screensize like function that gives offset, + * in practice the window manager will likely move to the correct monitor */ + wm_init_state.start_x = 0; + wm_init_state.start_y = 0; #ifdef WITH_X11 /* X11 */ - /* X11, don't start maximized because we can't figure out the dimensions - * of a single display yet if there are multiple, due to lack of Xinerama - * handling in GHOST. */ - wm_init_state.size_x = min_ii(wm_init_state.size_x, WM_WIN_INIT_SIZE_X); - wm_init_state.size_y = min_ii(wm_init_state.size_y, WM_WIN_INIT_SIZE_Y); - /* pad */ - wm_init_state.start_x = WM_WIN_INIT_PAD; - wm_init_state.start_y = WM_WIN_INIT_PAD; - wm_init_state.size_x -= WM_WIN_INIT_PAD * 2; - wm_init_state.size_y -= WM_WIN_INIT_PAD * 2; + /* X11, don't start maximized because we can't figure out the dimensions + * of a single display yet if there are multiple, due to lack of Xinerama + * handling in GHOST. */ + wm_init_state.size_x = min_ii(wm_init_state.size_x, WM_WIN_INIT_SIZE_X); + wm_init_state.size_y = min_ii(wm_init_state.size_y, WM_WIN_INIT_SIZE_Y); + /* pad */ + wm_init_state.start_x = WM_WIN_INIT_PAD; + wm_init_state.start_y = WM_WIN_INIT_PAD; + wm_init_state.size_x -= WM_WIN_INIT_PAD * 2; + wm_init_state.size_y -= WM_WIN_INIT_PAD * 2; #endif - } - - for (win = wm->windows.first; win; win = win->next) { - if (win->ghostwin == NULL) { - if ((win->sizex == 0) || (wm_init_state.override_flag & WIN_OVERRIDE_GEOM)) { - win->posx = wm_init_state.start_x; - win->posy = wm_init_state.start_y; - win->sizex = wm_init_state.size_x; - win->sizey = wm_init_state.size_y; - - if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) { - win->windowstate = GHOST_kWindowStateNormal; - wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM; - } - else { - win->windowstate = GHOST_WINDOW_STATE_DEFAULT; - } - } - - if (wm_init_state.override_flag & WIN_OVERRIDE_WINSTATE) { - win->windowstate = wm_init_state.windowstate; - wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE; - } - - /* without this, cursor restore may fail, T45456 */ - if (win->cursor == 0) { - win->cursor = CURSOR_STD; - } - - wm_window_ghostwindow_add(wm, "Blender", win); - } - /* happens after fileread */ - wm_window_ensure_eventstate(win); - - /* add keymap handlers (1 handler for all keys in map!) */ - keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0); - WM_event_add_keymap_handler(&win->handlers, keymap); - - keymap = WM_keymap_ensure(wm->defaultconf, "Screen", 0, 0); - WM_event_add_keymap_handler(&win->handlers, keymap); - - keymap = WM_keymap_ensure(wm->defaultconf, "Screen Editing", 0, 0); - WM_event_add_keymap_handler(&win->modalhandlers, keymap); - - /* add drop boxes */ - { - ListBase *lb = WM_dropboxmap_find("Window", 0, 0); - WM_event_add_dropbox_handler(&win->handlers, lb); - } - wm_window_title(wm, win); - - /* add topbar */ - ED_screen_global_areas_refresh(win); - } + } + + for (win = wm->windows.first; win; win = win->next) { + if (win->ghostwin == NULL) { + if ((win->sizex == 0) || (wm_init_state.override_flag & WIN_OVERRIDE_GEOM)) { + win->posx = wm_init_state.start_x; + win->posy = wm_init_state.start_y; + win->sizex = wm_init_state.size_x; + win->sizey = wm_init_state.size_y; + + if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) { + win->windowstate = GHOST_kWindowStateNormal; + wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM; + } + else { + win->windowstate = GHOST_WINDOW_STATE_DEFAULT; + } + } + + if (wm_init_state.override_flag & WIN_OVERRIDE_WINSTATE) { + win->windowstate = wm_init_state.windowstate; + wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE; + } + + /* without this, cursor restore may fail, T45456 */ + if (win->cursor == 0) { + win->cursor = CURSOR_STD; + } + + wm_window_ghostwindow_add(wm, "Blender", win); + } + /* happens after fileread */ + wm_window_ensure_eventstate(win); + + /* add keymap handlers (1 handler for all keys in map!) */ + keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0); + WM_event_add_keymap_handler(&win->handlers, keymap); + + keymap = WM_keymap_ensure(wm->defaultconf, "Screen", 0, 0); + WM_event_add_keymap_handler(&win->handlers, keymap); + + keymap = WM_keymap_ensure(wm->defaultconf, "Screen Editing", 0, 0); + WM_event_add_keymap_handler(&win->modalhandlers, keymap); + + /* add drop boxes */ + { + ListBase *lb = WM_dropboxmap_find("Window", 0, 0); + WM_event_add_dropbox_handler(&win->handlers, lb); + } + wm_window_title(wm, win); + + /* add topbar */ + ED_screen_global_areas_refresh(win); + } } /** @@ -833,16 +886,16 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm) */ void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm) { - wmWindow *win, *win_next; + wmWindow *win, *win_next; - BLI_assert(G.background == false); + BLI_assert(G.background == false); - for (win = wm->windows.first; win; win = win_next) { - win_next = win->next; - if (win->ghostwin == NULL) { - wm_window_close(C, wm, win); - } - } + for (win = wm->windows.first; win; win = win_next) { + win_next = win->next; + if (win->ghostwin == NULL) { + wm_window_close(C, wm, win); + } + } } /** @@ -853,24 +906,24 @@ void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm) */ wmWindow *WM_window_open(bContext *C, const rcti *rect) { - wmWindow *win_prev = CTX_wm_window(C); - wmWindow *win = wm_window_new(C, win_prev); + wmWindow *win_prev = CTX_wm_window(C); + wmWindow *win = wm_window_new(C, win_prev); - win->posx = rect->xmin; - win->posy = rect->ymin; - win->sizex = BLI_rcti_size_x(rect); - win->sizey = BLI_rcti_size_y(rect); + win->posx = rect->xmin; + win->posy = rect->ymin; + win->sizex = BLI_rcti_size_x(rect); + win->sizey = BLI_rcti_size_y(rect); - WM_check(C); + WM_check(C); - if (win->ghostwin) { - return win; - } - else { - wm_window_close(C, CTX_wm_manager(C), win); - CTX_wm_window_set(C, win_prev); - return NULL; - } + if (win->ghostwin) { + return win; + } + else { + wm_window_close(C, CTX_wm_manager(C), win); + CTX_wm_window_set(C, win_prev); + return NULL; + } } /** @@ -882,738 +935,722 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect) */ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, int type) { - Main *bmain = CTX_data_main(C); - wmWindow *win_prev = CTX_wm_window(C); - wmWindow *win; - bScreen *screen; - ScrArea *sa; - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - const char *title; - - /* convert to native OS window coordinates */ - const float native_pixel_size = GHOST_GetNativePixelSize(win_prev->ghostwin); - x /= native_pixel_size; - y /= native_pixel_size; - sizex /= native_pixel_size; - sizey /= native_pixel_size; - - /* calculate position */ - rcti rect; - rect.xmin = x + win_prev->posx - sizex / 2; - rect.ymin = y + win_prev->posy - sizey / 2; - rect.xmax = rect.xmin + sizex; - rect.ymax = rect.ymin + sizey; - - /* changes rect to fit within desktop */ - wm_window_check_position(&rect); - - /* test if we have a temp screen already */ - for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { - if (WM_window_is_temp_screen(win)) { - break; - } - } - - /* add new window? */ - if (win == NULL) { - win = wm_window_new(C, win_prev); - - win->posx = rect.xmin; - win->posy = rect.ymin; - } - - screen = WM_window_get_active_screen(win); - - win->sizex = BLI_rcti_size_x(&rect); - win->sizey = BLI_rcti_size_y(&rect); - - if (win->ghostwin) { - wm_window_set_size(win, win->sizex, win->sizey); - wm_window_raise(win); - } - - if (WM_window_get_active_workspace(win) == NULL) { - WorkSpace *workspace = WM_window_get_active_workspace(win_prev); - BKE_workspace_active_set(win->workspace_hook, workspace); - } - - if (screen == NULL) { - /* add new screen layout */ - WorkSpace *workspace = WM_window_get_active_workspace(win); - WorkSpaceLayout *layout = ED_workspace_layout_add(bmain, workspace, win, "temp"); - - screen = BKE_workspace_layout_screen_get(layout); - WM_window_set_active_layout(win, workspace, layout); - } - - /* Set scene and view layer to match original window. */ - STRNCPY(win->view_layer_name, view_layer->name); - if (WM_window_get_active_scene(win) != scene) { - ED_screen_scene_change(C, win, scene); - } - - screen->temp = 1; - - /* make window active, and validate/resize */ - CTX_wm_window_set(C, win); - WM_check(C); - - /* It's possible `win->ghostwin == NULL`. - * instead of attempting to cleanup here (in a half finished state), - * finish setting up the screen, then free it at the end of the function, - * to avoid having to take into account a partially-created window. - */ - - /* ensure it shows the right spacetype editor */ - sa = screen->areabase.first; - CTX_wm_area_set(C, sa); - - if (type == WM_WINDOW_RENDER) { - ED_area_newspace(C, sa, SPACE_IMAGE, false); - } - else if (type == WM_WINDOW_DRIVERS) { - ED_area_newspace(C, sa, SPACE_GRAPH, false); - } - else { - ED_area_newspace(C, sa, SPACE_USERPREF, false); - } - - ED_screen_change(C, screen); - ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */ - - /* do additional setup for specific editor type */ - if (type == WM_WINDOW_DRIVERS) { - ED_drivers_editor_init(C, sa); - } - - if (sa->spacetype == SPACE_IMAGE) { - title = IFACE_("Blender Render"); - } - else if (ELEM(sa->spacetype, SPACE_OUTLINER, SPACE_USERPREF)) { - title = IFACE_("Blender Preferences"); - } - else if (sa->spacetype == SPACE_FILE) { - title = IFACE_("Blender File View"); - } - else if (sa->spacetype == SPACE_GRAPH) { - title = IFACE_("Blender Drivers Editor"); - } - else { - title = "Blender"; - } - - if (win->ghostwin) { - GHOST_SetTitle(win->ghostwin, title); - return win; - } - else { - /* very unlikely! but opening a new window can fail */ - wm_window_close(C, CTX_wm_manager(C), win); - CTX_wm_window_set(C, win_prev); - - return NULL; - } + Main *bmain = CTX_data_main(C); + wmWindow *win_prev = CTX_wm_window(C); + wmWindow *win; + bScreen *screen; + ScrArea *sa; + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const char *title; + + /* convert to native OS window coordinates */ + const float native_pixel_size = GHOST_GetNativePixelSize(win_prev->ghostwin); + x /= native_pixel_size; + y /= native_pixel_size; + sizex /= native_pixel_size; + sizey /= native_pixel_size; + + /* calculate position */ + rcti rect; + rect.xmin = x + win_prev->posx - sizex / 2; + rect.ymin = y + win_prev->posy - sizey / 2; + rect.xmax = rect.xmin + sizex; + rect.ymax = rect.ymin + sizey; + + /* changes rect to fit within desktop */ + wm_window_check_position(&rect); + + /* test if we have a temp screen already */ + for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { + if (WM_window_is_temp_screen(win)) { + break; + } + } + + /* add new window? */ + if (win == NULL) { + win = wm_window_new(C, win_prev); + + win->posx = rect.xmin; + win->posy = rect.ymin; + } + + screen = WM_window_get_active_screen(win); + + win->sizex = BLI_rcti_size_x(&rect); + win->sizey = BLI_rcti_size_y(&rect); + + if (win->ghostwin) { + wm_window_set_size(win, win->sizex, win->sizey); + wm_window_raise(win); + } + + if (WM_window_get_active_workspace(win) == NULL) { + WorkSpace *workspace = WM_window_get_active_workspace(win_prev); + BKE_workspace_active_set(win->workspace_hook, workspace); + } + + if (screen == NULL) { + /* add new screen layout */ + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout = ED_workspace_layout_add(bmain, workspace, win, "temp"); + + screen = BKE_workspace_layout_screen_get(layout); + WM_window_set_active_layout(win, workspace, layout); + } + + /* Set scene and view layer to match original window. */ + STRNCPY(win->view_layer_name, view_layer->name); + if (WM_window_get_active_scene(win) != scene) { + ED_screen_scene_change(C, win, scene); + } + + screen->temp = 1; + + /* make window active, and validate/resize */ + CTX_wm_window_set(C, win); + WM_check(C); + + /* It's possible `win->ghostwin == NULL`. + * instead of attempting to cleanup here (in a half finished state), + * finish setting up the screen, then free it at the end of the function, + * to avoid having to take into account a partially-created window. + */ + + /* ensure it shows the right spacetype editor */ + sa = screen->areabase.first; + CTX_wm_area_set(C, sa); + + if (type == WM_WINDOW_RENDER) { + ED_area_newspace(C, sa, SPACE_IMAGE, false); + } + else if (type == WM_WINDOW_DRIVERS) { + ED_area_newspace(C, sa, SPACE_GRAPH, false); + } + else { + ED_area_newspace(C, sa, SPACE_USERPREF, false); + } + + ED_screen_change(C, screen); + ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */ + + /* do additional setup for specific editor type */ + if (type == WM_WINDOW_DRIVERS) { + ED_drivers_editor_init(C, sa); + } + + if (sa->spacetype == SPACE_IMAGE) { + title = IFACE_("Blender Render"); + } + else if (ELEM(sa->spacetype, SPACE_OUTLINER, SPACE_USERPREF)) { + title = IFACE_("Blender Preferences"); + } + else if (sa->spacetype == SPACE_FILE) { + title = IFACE_("Blender File View"); + } + else if (sa->spacetype == SPACE_GRAPH) { + title = IFACE_("Blender Drivers Editor"); + } + else { + title = "Blender"; + } + + if (win->ghostwin) { + GHOST_SetTitle(win->ghostwin, title); + return win; + } + else { + /* very unlikely! but opening a new window can fail */ + wm_window_close(C, CTX_wm_manager(C), win); + CTX_wm_window_set(C, win_prev); + + return NULL; + } } - /* ****************** Operators ****************** */ int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op)) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - wm_window_close(C, wm, win); - return OPERATOR_FINISHED; + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + wm_window_close(C, wm, win); + return OPERATOR_FINISHED; } int wm_window_new_exec(bContext *C, wmOperator *UNUSED(op)) { - wmWindow *win_src = CTX_wm_window(C); - bool ok; + wmWindow *win_src = CTX_wm_window(C); + bool ok; - ok = (wm_window_copy_test(C, win_src, true, true) != NULL); + ok = (wm_window_copy_test(C, win_src, true, true) != NULL); - return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } int wm_window_new_main_exec(bContext *C, wmOperator *UNUSED(op)) { - wmWindow *win_src = CTX_wm_window(C); - bool ok; + wmWindow *win_src = CTX_wm_window(C); + bool ok; - ok = (wm_window_copy_test(C, win_src, true, false) != NULL); + ok = (wm_window_copy_test(C, win_src, true, false) != NULL); - return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } /* fullscreen operator callback */ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { - wmWindow *window = CTX_wm_window(C); - GHOST_TWindowState state; - - if (G.background) { - return OPERATOR_CANCELLED; - } + wmWindow *window = CTX_wm_window(C); + GHOST_TWindowState state; - state = GHOST_GetWindowState(window->ghostwin); - if (state != GHOST_kWindowStateFullScreen) { - GHOST_SetWindowState(window->ghostwin, GHOST_kWindowStateFullScreen); - } - else { - GHOST_SetWindowState(window->ghostwin, GHOST_kWindowStateNormal); - } + if (G.background) { + return OPERATOR_CANCELLED; + } - return OPERATOR_FINISHED; + state = GHOST_GetWindowState(window->ghostwin); + if (state != GHOST_kWindowStateFullScreen) { + GHOST_SetWindowState(window->ghostwin, GHOST_kWindowStateFullScreen); + } + else { + GHOST_SetWindowState(window->ghostwin, GHOST_kWindowStateNormal); + } + return OPERATOR_FINISHED; } - /* ************ events *************** */ void wm_cursor_position_from_ghost(wmWindow *win, int *x, int *y) { - float fac = GHOST_GetNativePixelSize(win->ghostwin); + float fac = GHOST_GetNativePixelSize(win->ghostwin); - GHOST_ScreenToClient(win->ghostwin, *x, *y, x, y); - *x *= fac; + GHOST_ScreenToClient(win->ghostwin, *x, *y, x, y); + *x *= fac; - *y = (win->sizey - 1) - *y; - *y *= fac; + *y = (win->sizey - 1) - *y; + *y *= fac; } void wm_cursor_position_to_ghost(wmWindow *win, int *x, int *y) { - float fac = GHOST_GetNativePixelSize(win->ghostwin); + float fac = GHOST_GetNativePixelSize(win->ghostwin); - *x /= fac; - *y /= fac; - *y = win->sizey - *y - 1; + *x /= fac; + *y /= fac; + *y = win->sizey - *y - 1; - GHOST_ClientToScreen(win->ghostwin, *x, *y, x, y); + GHOST_ClientToScreen(win->ghostwin, *x, *y, x, y); } void wm_get_cursor_position(wmWindow *win, int *x, int *y) { - if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) { - *x = win->eventstate->x; - *y = win->eventstate->y; - return; - } - GHOST_GetCursorPosition(g_system, x, y); - wm_cursor_position_from_ghost(win, x, y); + if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) { + *x = win->eventstate->x; + *y = win->eventstate->y; + return; + } + GHOST_GetCursorPosition(g_system, x, y); + wm_cursor_position_from_ghost(win, x, y); } typedef enum { - SHIFT = 's', - CONTROL = 'c', - ALT = 'a', - OS = 'C', + SHIFT = 's', + CONTROL = 'c', + ALT = 'a', + OS = 'C', } modifierKeyType; /* check if specified modifier key type is pressed */ static int query_qual(modifierKeyType qual) { - GHOST_TModifierKeyMask left, right; - int val = 0; - - switch (qual) { - case SHIFT: - left = GHOST_kModifierKeyLeftShift; - right = GHOST_kModifierKeyRightShift; - break; - case CONTROL: - left = GHOST_kModifierKeyLeftControl; - right = GHOST_kModifierKeyRightControl; - break; - case OS: - left = right = GHOST_kModifierKeyOS; - break; - case ALT: - default: - left = GHOST_kModifierKeyLeftAlt; - right = GHOST_kModifierKeyRightAlt; - break; - } - - GHOST_GetModifierKeyState(g_system, left, &val); - if (!val) { - GHOST_GetModifierKeyState(g_system, right, &val); - } - - return val; + GHOST_TModifierKeyMask left, right; + int val = 0; + + switch (qual) { + case SHIFT: + left = GHOST_kModifierKeyLeftShift; + right = GHOST_kModifierKeyRightShift; + break; + case CONTROL: + left = GHOST_kModifierKeyLeftControl; + right = GHOST_kModifierKeyRightControl; + break; + case OS: + left = right = GHOST_kModifierKeyOS; + break; + case ALT: + default: + left = GHOST_kModifierKeyLeftAlt; + right = GHOST_kModifierKeyRightAlt; + break; + } + + GHOST_GetModifierKeyState(g_system, left, &val); + if (!val) { + GHOST_GetModifierKeyState(g_system, right, &val); + } + + return val; } static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool activate) { - BLI_assert(ELEM(wm->windrawable, NULL, win)); + BLI_assert(ELEM(wm->windrawable, NULL, win)); - wm->windrawable = win; - if (activate) { - GHOST_ActivateWindowDrawingContext(win->ghostwin); - } - GPU_context_active_set(win->gpuctx); - immActivate(); + wm->windrawable = win; + if (activate) { + GHOST_ActivateWindowDrawingContext(win->ghostwin); + } + GPU_context_active_set(win->gpuctx); + immActivate(); } void wm_window_clear_drawable(wmWindowManager *wm) { - if (wm->windrawable) { - BLF_batch_reset(); - gpu_batch_presets_reset(); - immDeactivate(); - wm->windrawable = NULL; - } + if (wm->windrawable) { + BLF_batch_reset(); + gpu_batch_presets_reset(); + immDeactivate(); + wm->windrawable = NULL; + } } void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) { - BLI_assert(GPU_framebuffer_active_get() == NULL); + BLI_assert(GPU_framebuffer_active_get() == NULL); - if (win != wm->windrawable && win->ghostwin) { -// win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */ - wm_window_clear_drawable(wm); + if (win != wm->windrawable && win->ghostwin) { + // win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */ + wm_window_clear_drawable(wm); - if (G.debug & G_DEBUG_EVENTS) { - printf("%s: set drawable %d\n", __func__, win->winid); - } + if (G.debug & G_DEBUG_EVENTS) { + printf("%s: set drawable %d\n", __func__, win->winid); + } - wm_window_set_drawable(wm, win, true); + wm_window_set_drawable(wm, win, true); - /* this can change per window */ - WM_window_set_dpi(win); - } + /* this can change per window */ + WM_window_set_dpi(win); + } } /* Reset active the current window opengl drawing context. */ void wm_window_reset_drawable(void) { - BLI_assert(BLI_thread_is_main()); - BLI_assert(GPU_framebuffer_active_get() == NULL); - wmWindowManager *wm = G_MAIN->wm.first; + BLI_assert(BLI_thread_is_main()); + BLI_assert(GPU_framebuffer_active_get() == NULL); + wmWindowManager *wm = G_MAIN->wm.first; - if (wm == NULL) { - return; - } - wmWindow *win = wm->windrawable; + if (wm == NULL) { + return; + } + wmWindow *win = wm->windrawable; - if (win && win->ghostwin) { - wm_window_clear_drawable(wm); - wm_window_set_drawable(wm, win, true); - } + if (win && win->ghostwin) { + wm_window_clear_drawable(wm); + wm_window_set_drawable(wm, win, true); + } } /* called by ghost, here we handle events for windows themselves or send to event system */ /* mouse coordinate converversion happens here */ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr) { - bContext *C = C_void_ptr; - wmWindowManager *wm = CTX_wm_manager(C); - GHOST_TEventType type = GHOST_GetEventType(evt); - int time = GHOST_GetEventTime(evt); - - if (type == GHOST_kEventQuit) { - WM_exit(C); - } - else { - GHOST_WindowHandle ghostwin = GHOST_GetEventWindow(evt); - GHOST_TEventDataPtr data = GHOST_GetEventData(evt); - wmWindow *win; - - /* Ghost now can call this function for life resizes, but it should return if WM didn't initialize yet. - * Can happen on file read (especially full size window) */ - if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) { - return 1; - } - if (!ghostwin) { - /* XXX - should be checked, why are we getting an event here, and */ - /* what is it? */ - puts("<!> event has no window"); - return 1; - } - else if (!GHOST_ValidWindow(g_system, ghostwin)) { - /* XXX - should be checked, why are we getting an event here, and */ - /* what is it? */ - puts("<!> event has invalid window"); - return 1; - } - else { - win = GHOST_GetWindowUserData(ghostwin); - } - - switch (type) { - case GHOST_kEventWindowDeactivate: - wm_event_add_ghostevent(wm, win, type, time, data); - win->active = 0; /* XXX */ - - /* clear modifiers for inactive windows */ - win->eventstate->alt = 0; - win->eventstate->ctrl = 0; - win->eventstate->shift = 0; - win->eventstate->oskey = 0; - win->eventstate->keymodifier = 0; - - break; - case GHOST_kEventWindowActivate: - { - GHOST_TEventKeyData kdata; - wmEvent event; - int wx, wy; - const int keymodifier = ((query_qual(SHIFT) ? KM_SHIFT : 0) | - (query_qual(CONTROL) ? KM_CTRL : 0) | - (query_qual(ALT) ? KM_ALT : 0) | - (query_qual(OS) ? KM_OSKEY : 0)); - - /* Win23/GHOST modifier bug, see T40317 */ + bContext *C = C_void_ptr; + wmWindowManager *wm = CTX_wm_manager(C); + GHOST_TEventType type = GHOST_GetEventType(evt); + int time = GHOST_GetEventTime(evt); + + if (type == GHOST_kEventQuit) { + WM_exit(C); + } + else { + GHOST_WindowHandle ghostwin = GHOST_GetEventWindow(evt); + GHOST_TEventDataPtr data = GHOST_GetEventData(evt); + wmWindow *win; + + /* Ghost now can call this function for life resizes, but it should return if WM didn't initialize yet. + * Can happen on file read (especially full size window) */ + if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) { + return 1; + } + if (!ghostwin) { + /* XXX - should be checked, why are we getting an event here, and */ + /* what is it? */ + puts("<!> event has no window"); + return 1; + } + else if (!GHOST_ValidWindow(g_system, ghostwin)) { + /* XXX - should be checked, why are we getting an event here, and */ + /* what is it? */ + puts("<!> event has invalid window"); + return 1; + } + else { + win = GHOST_GetWindowUserData(ghostwin); + } + + switch (type) { + case GHOST_kEventWindowDeactivate: + wm_event_add_ghostevent(wm, win, type, time, data); + win->active = 0; /* XXX */ + + /* clear modifiers for inactive windows */ + win->eventstate->alt = 0; + win->eventstate->ctrl = 0; + win->eventstate->shift = 0; + win->eventstate->oskey = 0; + win->eventstate->keymodifier = 0; + + break; + case GHOST_kEventWindowActivate: { + GHOST_TEventKeyData kdata; + wmEvent event; + int wx, wy; + const int keymodifier = ((query_qual(SHIFT) ? KM_SHIFT : 0) | + (query_qual(CONTROL) ? KM_CTRL : 0) | + (query_qual(ALT) ? KM_ALT : 0) | (query_qual(OS) ? KM_OSKEY : 0)); + + /* Win23/GHOST modifier bug, see T40317 */ #ifndef WIN32 //# define USE_WIN_ACTIVATE #endif - wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */ + wm->winactive = + win; /* no context change! c->wm->windrawable is drawable, or for area queues */ - win->active = 1; -// window_handle(win, INPUTCHANGE, win->active); + win->active = 1; + // window_handle(win, INPUTCHANGE, win->active); - /* bad ghost support for modifier keys... so on activate we set the modifiers again */ + /* bad ghost support for modifier keys... so on activate we set the modifiers again */ - /* TODO: This is not correct since a modifier may be held when a window is activated... - * better solve this at ghost level. attempted fix r54450 but it caused bug [#34255] - * - * For now don't send GHOST_kEventKeyDown events, just set the 'eventstate'. - */ - kdata.ascii = '\0'; - kdata.utf8_buf[0] = '\0'; + /* TODO: This is not correct since a modifier may be held when a window is activated... + * better solve this at ghost level. attempted fix r54450 but it caused bug [#34255] + * + * For now don't send GHOST_kEventKeyDown events, just set the 'eventstate'. + */ + kdata.ascii = '\0'; + kdata.utf8_buf[0] = '\0'; - if (win->eventstate->shift) { - if ((keymodifier & KM_SHIFT) == 0) { - kdata.key = GHOST_kKeyLeftShift; - wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); - } - } + if (win->eventstate->shift) { + if ((keymodifier & KM_SHIFT) == 0) { + kdata.key = GHOST_kKeyLeftShift; + wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); + } + } #ifdef USE_WIN_ACTIVATE - else { - if (keymodifier & KM_SHIFT) { - win->eventstate->shift = KM_MOD_FIRST; - } - } + else { + if (keymodifier & KM_SHIFT) { + win->eventstate->shift = KM_MOD_FIRST; + } + } #endif - if (win->eventstate->ctrl) { - if ((keymodifier & KM_CTRL) == 0) { - kdata.key = GHOST_kKeyLeftControl; - wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); - } - } + if (win->eventstate->ctrl) { + if ((keymodifier & KM_CTRL) == 0) { + kdata.key = GHOST_kKeyLeftControl; + wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); + } + } #ifdef USE_WIN_ACTIVATE - else { - if (keymodifier & KM_CTRL) { - win->eventstate->ctrl = KM_MOD_FIRST; - } - } + else { + if (keymodifier & KM_CTRL) { + win->eventstate->ctrl = KM_MOD_FIRST; + } + } #endif - if (win->eventstate->alt) { - if ((keymodifier & KM_ALT) == 0) { - kdata.key = GHOST_kKeyLeftAlt; - wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); - } - } + if (win->eventstate->alt) { + if ((keymodifier & KM_ALT) == 0) { + kdata.key = GHOST_kKeyLeftAlt; + wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); + } + } #ifdef USE_WIN_ACTIVATE - else { - if (keymodifier & KM_ALT) { - win->eventstate->alt = KM_MOD_FIRST; - } - } + else { + if (keymodifier & KM_ALT) { + win->eventstate->alt = KM_MOD_FIRST; + } + } #endif - if (win->eventstate->oskey) { - if ((keymodifier & KM_OSKEY) == 0) { - kdata.key = GHOST_kKeyOS; - wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); - } - } + if (win->eventstate->oskey) { + if ((keymodifier & KM_OSKEY) == 0) { + kdata.key = GHOST_kKeyOS; + wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); + } + } #ifdef USE_WIN_ACTIVATE - else { - if (keymodifier & KM_OSKEY) { - win->eventstate->oskey = KM_MOD_FIRST; - } - } + else { + if (keymodifier & KM_OSKEY) { + win->eventstate->oskey = KM_MOD_FIRST; + } + } #endif #undef USE_WIN_ACTIVATE - - /* keymodifier zero, it hangs on hotkeys that open windows otherwise */ - win->eventstate->keymodifier = 0; - - /* entering window, update mouse pos. but no event */ - wm_get_cursor_position(win, &wx, &wy); - - win->eventstate->x = wx; - win->eventstate->y = wy; - - win->addmousemove = 1; /* enables highlighted buttons */ - - wm_window_make_drawable(wm, win); - - /* window might be focused by mouse click in configuration of window manager - * when focus is not following mouse - * click could have been done on a button and depending on window manager settings - * click would be passed to blender or not, but in any case button under cursor - * should be activated, so at max next click on button without moving mouse - * would trigger it's handle function - * currently it seems to be common practice to generate new event for, but probably - * we'll need utility function for this? (sergey) - */ - wm_event_init_from_window(win, &event); - event.type = MOUSEMOVE; - event.prevx = event.x; - event.prevy = event.y; - - wm_event_add(win, &event); - - break; - } - case GHOST_kEventWindowClose: - { - wm_window_close(C, wm, win); - break; - } - case GHOST_kEventWindowUpdate: - { - if (G.debug & G_DEBUG_EVENTS) { - printf("%s: ghost redraw %d\n", __func__, win->winid); - } - - wm_window_make_drawable(wm, win); - WM_event_add_notifier(C, NC_WINDOW, NULL); - - break; - } - case GHOST_kEventWindowSize: - case GHOST_kEventWindowMove: - { - GHOST_TWindowState state; - state = GHOST_GetWindowState(win->ghostwin); - win->windowstate = state; - - WM_window_set_dpi(win); - - /* win32: gives undefined window size when minimized */ - if (state != GHOST_kWindowStateMinimized) { - GHOST_RectangleHandle client_rect; - int l, t, r, b, scr_w, scr_h; - int sizex, sizey, posx, posy; - - client_rect = GHOST_GetClientBounds(win->ghostwin); - GHOST_GetRectangle(client_rect, &l, &t, &r, &b); - - GHOST_DisposeRectangle(client_rect); - - wm_get_desktopsize(&scr_w, &scr_h); - sizex = r - l; - sizey = b - t; - posx = l; - posy = scr_h - t - win->sizey; - - /* - * Ghost sometimes send size or move events when the window hasn't changed. - * One case of this is using compiz on linux. To alleviate the problem - * we ignore all such event here. - * - * It might be good to eventually do that at Ghost level, but that is for - * another time. - */ - if (win->sizex != sizex || - win->sizey != sizey || - win->posx != posx || - win->posy != posy) - { - const bScreen *screen = WM_window_get_active_screen(win); - - win->sizex = sizex; - win->sizey = sizey; - win->posx = posx; - win->posy = posy; - - /* debug prints */ - if (G.debug & G_DEBUG_EVENTS) { - const char *state_str; - state = GHOST_GetWindowState(win->ghostwin); - - if (state == GHOST_kWindowStateNormal) { - state_str = "normal"; - } - else if (state == GHOST_kWindowStateMinimized) { - state_str = "minimized"; - } - else if (state == GHOST_kWindowStateMaximized) { - state_str = "maximized"; - } - else if (state == GHOST_kWindowStateFullScreen) { - state_str = "fullscreen"; - } - else { - state_str = "<unknown>"; - } - - printf("%s: window %d state = %s\n", __func__, win->winid, state_str); - - if (type != GHOST_kEventWindowSize) { - printf("win move event pos %d %d size %d %d\n", - win->posx, win->posy, win->sizex, win->sizey); - } - } - - wm_window_make_drawable(wm, win); - BKE_icon_changed(screen->id.icon_id); - WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); + /* keymodifier zero, it hangs on hotkeys that open windows otherwise */ + win->eventstate->keymodifier = 0; + + /* entering window, update mouse pos. but no event */ + wm_get_cursor_position(win, &wx, &wy); + + win->eventstate->x = wx; + win->eventstate->y = wy; + + win->addmousemove = 1; /* enables highlighted buttons */ + + wm_window_make_drawable(wm, win); + + /* window might be focused by mouse click in configuration of window manager + * when focus is not following mouse + * click could have been done on a button and depending on window manager settings + * click would be passed to blender or not, but in any case button under cursor + * should be activated, so at max next click on button without moving mouse + * would trigger it's handle function + * currently it seems to be common practice to generate new event for, but probably + * we'll need utility function for this? (sergey) + */ + wm_event_init_from_window(win, &event); + event.type = MOUSEMOVE; + event.prevx = event.x; + event.prevy = event.y; + + wm_event_add(win, &event); + + break; + } + case GHOST_kEventWindowClose: { + wm_window_close(C, wm, win); + break; + } + case GHOST_kEventWindowUpdate: { + if (G.debug & G_DEBUG_EVENTS) { + printf("%s: ghost redraw %d\n", __func__, win->winid); + } + + wm_window_make_drawable(wm, win); + WM_event_add_notifier(C, NC_WINDOW, NULL); + + break; + } + case GHOST_kEventWindowSize: + case GHOST_kEventWindowMove: { + GHOST_TWindowState state; + state = GHOST_GetWindowState(win->ghostwin); + win->windowstate = state; + + WM_window_set_dpi(win); + + /* win32: gives undefined window size when minimized */ + if (state != GHOST_kWindowStateMinimized) { + GHOST_RectangleHandle client_rect; + int l, t, r, b, scr_w, scr_h; + int sizex, sizey, posx, posy; + + client_rect = GHOST_GetClientBounds(win->ghostwin); + GHOST_GetRectangle(client_rect, &l, &t, &r, &b); + + GHOST_DisposeRectangle(client_rect); + + wm_get_desktopsize(&scr_w, &scr_h); + sizex = r - l; + sizey = b - t; + posx = l; + posy = scr_h - t - win->sizey; + + /* + * Ghost sometimes send size or move events when the window hasn't changed. + * One case of this is using compiz on linux. To alleviate the problem + * we ignore all such event here. + * + * It might be good to eventually do that at Ghost level, but that is for + * another time. + */ + if (win->sizex != sizex || win->sizey != sizey || win->posx != posx || + win->posy != posy) { + const bScreen *screen = WM_window_get_active_screen(win); + + win->sizex = sizex; + win->sizey = sizey; + win->posx = posx; + win->posy = posy; + + /* debug prints */ + if (G.debug & G_DEBUG_EVENTS) { + const char *state_str; + state = GHOST_GetWindowState(win->ghostwin); + + if (state == GHOST_kWindowStateNormal) { + state_str = "normal"; + } + else if (state == GHOST_kWindowStateMinimized) { + state_str = "minimized"; + } + else if (state == GHOST_kWindowStateMaximized) { + state_str = "maximized"; + } + else if (state == GHOST_kWindowStateFullScreen) { + state_str = "fullscreen"; + } + else { + state_str = "<unknown>"; + } + + printf("%s: window %d state = %s\n", __func__, win->winid, state_str); + + if (type != GHOST_kEventWindowSize) { + printf("win move event pos %d %d size %d %d\n", + win->posx, + win->posy, + win->sizex, + win->sizey); + } + } + + wm_window_make_drawable(wm, win); + BKE_icon_changed(screen->id.icon_id); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); #if defined(__APPLE__) || defined(WIN32) - /* OSX and Win32 don't return to the mainloop while resize */ - wm_window_timer(C); - wm_event_do_handlers(C); - wm_event_do_notifiers(C); - wm_draw_update(C); + /* OSX and Win32 don't return to the mainloop while resize */ + wm_window_timer(C); + wm_event_do_handlers(C); + wm_event_do_notifiers(C); + wm_draw_update(C); #endif - } - } - break; - } - - case GHOST_kEventWindowDPIHintChanged: - { - WM_window_set_dpi(win); - /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ - BLF_cache_clear(); - - WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ - WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ - break; - } - - case GHOST_kEventOpenMainFile: - { - PointerRNA props_ptr; - const char *path = GHOST_GetEventData(evt); - - if (path) { - wmOperatorType *ot = WM_operatortype_find("WM_OT_open_mainfile", false); - /* operator needs a valid window in context, ensures - * it is correctly set */ - CTX_wm_window_set(C, win); - - WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_string_set(&props_ptr, "filepath", path); - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr); - WM_operator_properties_free(&props_ptr); - - CTX_wm_window_set(C, NULL); - } - break; - } - case GHOST_kEventDraggingDropDone: - { - wmEvent event; - GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); - int wx, wy; - - /* entering window, update mouse pos */ - wm_get_cursor_position(win, &wx, &wy); - win->eventstate->x = wx; - win->eventstate->y = wy; - - wm_event_init_from_window(win, &event); /* copy last state, like mouse coords */ - - /* activate region */ - event.type = MOUSEMOVE; - event.prevx = event.x; - event.prevy = event.y; - - wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */ - win->active = 1; - - wm_event_add(win, &event); - - - /* make blender drop event with custom data pointing to wm drags */ - event.type = EVT_DROP; - event.val = KM_RELEASE; - event.custom = EVT_DATA_DRAGDROP; - event.customdata = &wm->drags; - event.customdatafree = 1; - - wm_event_add(win, &event); - - /* printf("Drop detected\n"); */ - - /* add drag data to wm for paths: */ - - if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { - GHOST_TStringArray *stra = ddd->data; - int a, icon; - - for (a = 0; a < stra->count; a++) { - printf("drop file %s\n", stra->strings[a]); - /* try to get icon type from extension */ - icon = ED_file_extension_icon((char *)stra->strings[a]); - - WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0, WM_DRAG_NOP); - /* void poin should point to string, it makes a copy */ - break; /* only one drop element supported now */ - } - } - - break; - } - case GHOST_kEventNativeResolutionChange: - { - // only update if the actual pixel size changes - float prev_pixelsize = U.pixelsize; - WM_window_set_dpi(win); - - if (U.pixelsize != prev_pixelsize) { - BKE_icon_changed(WM_window_get_active_screen(win)->id.icon_id); - - // close all popups since they are positioned with the pixel - // size baked in and it's difficult to correct them - CTX_wm_window_set(C, win); - UI_popup_handlers_remove_all(C, &win->modalhandlers); - CTX_wm_window_set(C, NULL); - - wm_window_make_drawable(wm, win); - - WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); - } - - break; - } - case GHOST_kEventTrackpad: - { - GHOST_TEventTrackpadData *pd = data; - - wm_cursor_position_from_ghost(win, &pd->x, &pd->y); - wm_event_add_ghostevent(wm, win, type, time, data); - break; - } - case GHOST_kEventCursorMove: - { - GHOST_TEventCursorData *cd = data; - - wm_cursor_position_from_ghost(win, &cd->x, &cd->y); - wm_event_add_ghostevent(wm, win, type, time, data); - break; - } - default: - wm_event_add_ghostevent(wm, win, type, time, data); - break; - } - - } - return 1; + } + } + break; + } + + case GHOST_kEventWindowDPIHintChanged: { + WM_window_set_dpi(win); + /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ + BLF_cache_clear(); + + WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ + WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ + break; + } + + case GHOST_kEventOpenMainFile: { + PointerRNA props_ptr; + const char *path = GHOST_GetEventData(evt); + + if (path) { + wmOperatorType *ot = WM_operatortype_find("WM_OT_open_mainfile", false); + /* operator needs a valid window in context, ensures + * it is correctly set */ + CTX_wm_window_set(C, win); + + WM_operator_properties_create_ptr(&props_ptr, ot); + RNA_string_set(&props_ptr, "filepath", path); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); + + CTX_wm_window_set(C, NULL); + } + break; + } + case GHOST_kEventDraggingDropDone: { + wmEvent event; + GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); + int wx, wy; + + /* entering window, update mouse pos */ + wm_get_cursor_position(win, &wx, &wy); + win->eventstate->x = wx; + win->eventstate->y = wy; + + wm_event_init_from_window(win, &event); /* copy last state, like mouse coords */ + + /* activate region */ + event.type = MOUSEMOVE; + event.prevx = event.x; + event.prevy = event.y; + + wm->winactive = + win; /* no context change! c->wm->windrawable is drawable, or for area queues */ + win->active = 1; + + wm_event_add(win, &event); + + /* make blender drop event with custom data pointing to wm drags */ + event.type = EVT_DROP; + event.val = KM_RELEASE; + event.custom = EVT_DATA_DRAGDROP; + event.customdata = &wm->drags; + event.customdatafree = 1; + + wm_event_add(win, &event); + + /* printf("Drop detected\n"); */ + + /* add drag data to wm for paths: */ + + if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { + GHOST_TStringArray *stra = ddd->data; + int a, icon; + + for (a = 0; a < stra->count; a++) { + printf("drop file %s\n", stra->strings[a]); + /* try to get icon type from extension */ + icon = ED_file_extension_icon((char *)stra->strings[a]); + + WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0, WM_DRAG_NOP); + /* void poin should point to string, it makes a copy */ + break; /* only one drop element supported now */ + } + } + + break; + } + case GHOST_kEventNativeResolutionChange: { + // only update if the actual pixel size changes + float prev_pixelsize = U.pixelsize; + WM_window_set_dpi(win); + + if (U.pixelsize != prev_pixelsize) { + BKE_icon_changed(WM_window_get_active_screen(win)->id.icon_id); + + // close all popups since they are positioned with the pixel + // size baked in and it's difficult to correct them + CTX_wm_window_set(C, win); + UI_popup_handlers_remove_all(C, &win->modalhandlers); + CTX_wm_window_set(C, NULL); + + wm_window_make_drawable(wm, win); + + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); + } + + break; + } + case GHOST_kEventTrackpad: { + GHOST_TEventTrackpadData *pd = data; + + wm_cursor_position_from_ghost(win, &pd->x, &pd->y); + wm_event_add_ghostevent(wm, win, type, time, data); + break; + } + case GHOST_kEventCursorMove: { + GHOST_TEventCursorData *cd = data; + + wm_cursor_position_from_ghost(win, &cd->x, &cd->y); + wm_event_add_ghostevent(wm, win, type, time, data); + break; + } + default: + wm_event_add_ghostevent(wm, win, type, time, data); + break; + } + } + return 1; } - /** * This timer system only gives maximum 1 timer event per redraw cycle, * to prevent queues to get overloaded. @@ -1622,68 +1659,68 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr */ static int wm_window_timer(const bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - wmTimer *wt, *wtnext; - wmWindow *win; - double time = PIL_check_seconds_timer(); - int retval = 0; - - for (wt = wm->timers.first; wt; wt = wtnext) { - wtnext = wt->next; /* in case timer gets removed */ - win = wt->win; - - if (wt->sleep == 0) { - if (time > wt->ntime) { - wt->delta = time - wt->ltime; - wt->duration += wt->delta; - wt->ltime = time; - wt->ntime = wt->stime + wt->timestep * ceil(wt->duration / wt->timestep); - - if (wt->event_type == TIMERJOBS) { - wm_jobs_timer(C, wm, wt); - } - else if (wt->event_type == TIMERAUTOSAVE) { - wm_autosave_timer(C, wm, wt); - } - else if (wt->event_type == TIMERNOTIFIER) { - WM_main_add_notifier(POINTER_AS_UINT(wt->customdata), NULL); - } - else if (win) { - wmEvent event; - wm_event_init_from_window(win, &event); - - event.type = wt->event_type; - event.val = KM_NOTHING; - event.keymodifier = 0; - event.custom = EVT_DATA_TIMER; - event.customdata = wt; - wm_event_add(win, &event); - - retval = 1; - } - } - } - } - return retval; + wmWindowManager *wm = CTX_wm_manager(C); + wmTimer *wt, *wtnext; + wmWindow *win; + double time = PIL_check_seconds_timer(); + int retval = 0; + + for (wt = wm->timers.first; wt; wt = wtnext) { + wtnext = wt->next; /* in case timer gets removed */ + win = wt->win; + + if (wt->sleep == 0) { + if (time > wt->ntime) { + wt->delta = time - wt->ltime; + wt->duration += wt->delta; + wt->ltime = time; + wt->ntime = wt->stime + wt->timestep * ceil(wt->duration / wt->timestep); + + if (wt->event_type == TIMERJOBS) { + wm_jobs_timer(C, wm, wt); + } + else if (wt->event_type == TIMERAUTOSAVE) { + wm_autosave_timer(C, wm, wt); + } + else if (wt->event_type == TIMERNOTIFIER) { + WM_main_add_notifier(POINTER_AS_UINT(wt->customdata), NULL); + } + else if (win) { + wmEvent event; + wm_event_init_from_window(win, &event); + + event.type = wt->event_type; + event.val = KM_NOTHING; + event.keymodifier = 0; + event.custom = EVT_DATA_TIMER; + event.customdata = wt; + wm_event_add(win, &event); + + retval = 1; + } + } + } + } + return retval; } void wm_window_process_events(const bContext *C) { - int hasevent; + int hasevent; - BLI_assert(BLI_thread_is_main()); + BLI_assert(BLI_thread_is_main()); - hasevent = GHOST_ProcessEvents(g_system, 0); /* 0 is no wait */ + hasevent = GHOST_ProcessEvents(g_system, 0); /* 0 is no wait */ - if (hasevent) { - GHOST_DispatchEvents(g_system); - } - hasevent |= wm_window_timer(C); + if (hasevent) { + GHOST_DispatchEvents(g_system); + } + hasevent |= wm_window_timer(C); - /* no event, we sleep 5 milliseconds */ - if (hasevent == 0) { - PIL_sleep_ms(5); - } + /* no event, we sleep 5 milliseconds */ + if (hasevent == 0) { + PIL_sleep_ms(5); + } } /* **************** init ********************** */ @@ -1692,178 +1729,183 @@ void wm_window_process_events(const bContext *C) * need to event handling. */ void wm_ghost_init(bContext *C) { - if (!g_system) { - GHOST_EventConsumerHandle consumer; + if (!g_system) { + GHOST_EventConsumerHandle consumer; - if (C != NULL) { - consumer = GHOST_CreateEventConsumer(ghost_event_proc, C); - } + if (C != NULL) { + consumer = GHOST_CreateEventConsumer(ghost_event_proc, C); + } - g_system = GHOST_CreateSystem(); + g_system = GHOST_CreateSystem(); - if (C != NULL) { - GHOST_AddEventConsumer(g_system, consumer); - } + if (C != NULL) { + GHOST_AddEventConsumer(g_system, consumer); + } - if (wm_init_state.native_pixels) { - GHOST_UseNativePixels(); - } + if (wm_init_state.native_pixels) { + GHOST_UseNativePixels(); + } - GHOST_UseWindowFocus(wm_init_state.window_focus); + GHOST_UseWindowFocus(wm_init_state.window_focus); - WM_init_tablet_api(); - } + WM_init_tablet_api(); + } } void wm_ghost_exit(void) { - if (g_system) { - GHOST_DisposeSystem(g_system); - } - g_system = NULL; + if (g_system) { + GHOST_DisposeSystem(g_system); + } + g_system = NULL; } /* **************** timer ********************** */ /* to (de)activate running timers temporary */ -void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer, bool do_sleep) +void WM_event_timer_sleep(wmWindowManager *wm, + wmWindow *UNUSED(win), + wmTimer *timer, + bool do_sleep) { - wmTimer *wt; + wmTimer *wt; - for (wt = wm->timers.first; wt; wt = wt->next) { - if (wt == timer) { - break; - } - } + for (wt = wm->timers.first; wt; wt = wt->next) { + if (wt == timer) { + break; + } + } - if (wt) { - wt->sleep = do_sleep; - } + if (wt) { + wt->sleep = do_sleep; + } } wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep) { - wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer"); + wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer"); - wt->event_type = event_type; - wt->ltime = PIL_check_seconds_timer(); - wt->ntime = wt->ltime + timestep; - wt->stime = wt->ltime; - wt->timestep = timestep; - wt->win = win; + wt->event_type = event_type; + wt->ltime = PIL_check_seconds_timer(); + wt->ntime = wt->ltime + timestep; + wt->stime = wt->ltime; + wt->timestep = timestep; + wt->win = win; - BLI_addtail(&wm->timers, wt); + BLI_addtail(&wm->timers, wt); - return wt; + return wt; } -wmTimer *WM_event_add_timer_notifier(wmWindowManager *wm, wmWindow *win, unsigned int type, double timestep) +wmTimer *WM_event_add_timer_notifier(wmWindowManager *wm, + wmWindow *win, + unsigned int type, + double timestep) { - wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer"); + wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer"); - wt->event_type = TIMERNOTIFIER; - wt->ltime = PIL_check_seconds_timer(); - wt->ntime = wt->ltime + timestep; - wt->stime = wt->ltime; - wt->timestep = timestep; - wt->win = win; - wt->customdata = POINTER_FROM_UINT(type); - wt->flags |= WM_TIMER_NO_FREE_CUSTOM_DATA; + wt->event_type = TIMERNOTIFIER; + wt->ltime = PIL_check_seconds_timer(); + wt->ntime = wt->ltime + timestep; + wt->stime = wt->ltime; + wt->timestep = timestep; + wt->win = win; + wt->customdata = POINTER_FROM_UINT(type); + wt->flags |= WM_TIMER_NO_FREE_CUSTOM_DATA; - BLI_addtail(&wm->timers, wt); + BLI_addtail(&wm->timers, wt); - return wt; + return wt; } void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer) { - wmTimer *wt; - - /* extra security check */ - for (wt = wm->timers.first; wt; wt = wt->next) { - if (wt == timer) { - break; - } - } - if (wt) { - wmWindow *win; - - if (wm->reports.reporttimer == wt) { - wm->reports.reporttimer = NULL; - } - - BLI_remlink(&wm->timers, wt); - if (wt->customdata != NULL && (wt->flags & WM_TIMER_NO_FREE_CUSTOM_DATA) == 0) { - MEM_freeN(wt->customdata); - } - MEM_freeN(wt); - - /* there might be events in queue with this timer as customdata */ - for (win = wm->windows.first; win; win = win->next) { - wmEvent *event; - for (event = win->queue.first; event; event = event->next) { - if (event->customdata == wt) { - event->customdata = NULL; - event->type = EVENT_NONE; /* timer users customdata, dont want NULL == NULL */ - } - } - } - } + wmTimer *wt; + + /* extra security check */ + for (wt = wm->timers.first; wt; wt = wt->next) { + if (wt == timer) { + break; + } + } + if (wt) { + wmWindow *win; + + if (wm->reports.reporttimer == wt) { + wm->reports.reporttimer = NULL; + } + + BLI_remlink(&wm->timers, wt); + if (wt->customdata != NULL && (wt->flags & WM_TIMER_NO_FREE_CUSTOM_DATA) == 0) { + MEM_freeN(wt->customdata); + } + MEM_freeN(wt); + + /* there might be events in queue with this timer as customdata */ + for (win = wm->windows.first; win; win = win->next) { + wmEvent *event; + for (event = win->queue.first; event; event = event->next) { + if (event->customdata == wt) { + event->customdata = NULL; + event->type = EVENT_NONE; /* timer users customdata, dont want NULL == NULL */ + } + } + } + } } void WM_event_remove_timer_notifier(wmWindowManager *wm, wmWindow *win, wmTimer *timer) { - timer->customdata = NULL; - WM_event_remove_timer(wm, win, timer); + timer->customdata = NULL; + WM_event_remove_timer(wm, win, timer); } /* ******************* clipboard **************** */ -static char *wm_clipboard_text_get_ex(bool selection, int *r_len, - bool firstline) +static char *wm_clipboard_text_get_ex(bool selection, int *r_len, bool firstline) { - char *p, *p2, *buf, *newbuf; + char *p, *p2, *buf, *newbuf; - if (G.background) { - *r_len = 0; - return NULL; - } + if (G.background) { + *r_len = 0; + return NULL; + } - buf = (char *)GHOST_getClipboard(selection); - if (!buf) { - *r_len = 0; - return NULL; - } + buf = (char *)GHOST_getClipboard(selection); + if (!buf) { + *r_len = 0; + return NULL; + } - /* always convert from \r\n to \n */ - p2 = newbuf = MEM_mallocN(strlen(buf) + 1, __func__); + /* always convert from \r\n to \n */ + p2 = newbuf = MEM_mallocN(strlen(buf) + 1, __func__); - if (firstline) { - /* will return an over-alloc'ed value in the case there are newlines */ - for (p = buf; *p; p++) { - if ((*p != '\n') && (*p != '\r')) { - *(p2++) = *p; - } - else { - break; - } - } - } - else { - for (p = buf; *p; p++) { - if (*p != '\r') { - *(p2++) = *p; - } - } - } + if (firstline) { + /* will return an over-alloc'ed value in the case there are newlines */ + for (p = buf; *p; p++) { + if ((*p != '\n') && (*p != '\r')) { + *(p2++) = *p; + } + else { + break; + } + } + } + else { + for (p = buf; *p; p++) { + if (*p != '\r') { + *(p2++) = *p; + } + } + } - *p2 = '\0'; + *p2 = '\0'; - free(buf); /* ghost uses regular malloc */ + free(buf); /* ghost uses regular malloc */ - *r_len = (p2 - newbuf); + *r_len = (p2 - newbuf); - return newbuf; + return newbuf; } /** @@ -1873,7 +1915,7 @@ static char *wm_clipboard_text_get_ex(bool selection, int *r_len, */ char *WM_clipboard_text_get(bool selection, int *r_len) { - return wm_clipboard_text_get_ex(selection, r_len, false); + return wm_clipboard_text_get_ex(selection, r_len, false); } /** @@ -1881,173 +1923,172 @@ char *WM_clipboard_text_get(bool selection, int *r_len) */ char *WM_clipboard_text_get_firstline(bool selection, int *r_len) { - return wm_clipboard_text_get_ex(selection, r_len, true); + return wm_clipboard_text_get_ex(selection, r_len, true); } void WM_clipboard_text_set(const char *buf, bool selection) { - if (!G.background) { + if (!G.background) { #ifdef _WIN32 - /* do conversion from \n to \r\n on Windows */ - const char *p; - char *p2, *newbuf; - int newlen = 0; - - for (p = buf; *p; p++) { - if (*p == '\n') { - newlen += 2; - } - else { - newlen++; - } - } - - newbuf = MEM_callocN(newlen + 1, "WM_clipboard_text_set"); - - for (p = buf, p2 = newbuf; *p; p++, p2++) { - if (*p == '\n') { - *(p2++) = '\r'; *p2 = '\n'; - } - else { - *p2 = *p; - } - } - *p2 = '\0'; - - GHOST_putClipboard((GHOST_TInt8 *)newbuf, selection); - MEM_freeN(newbuf); + /* do conversion from \n to \r\n on Windows */ + const char *p; + char *p2, *newbuf; + int newlen = 0; + + for (p = buf; *p; p++) { + if (*p == '\n') { + newlen += 2; + } + else { + newlen++; + } + } + + newbuf = MEM_callocN(newlen + 1, "WM_clipboard_text_set"); + + for (p = buf, p2 = newbuf; *p; p++, p2++) { + if (*p == '\n') { + *(p2++) = '\r'; + *p2 = '\n'; + } + else { + *p2 = *p; + } + } + *p2 = '\0'; + + GHOST_putClipboard((GHOST_TInt8 *)newbuf, selection); + MEM_freeN(newbuf); #else - GHOST_putClipboard((GHOST_TInt8 *)buf, selection); + GHOST_putClipboard((GHOST_TInt8 *)buf, selection); #endif - } + } } /* ******************* progress bar **************** */ void WM_progress_set(wmWindow *win, float progress) { - GHOST_SetProgressBar(win->ghostwin, progress); + GHOST_SetProgressBar(win->ghostwin, progress); } void WM_progress_clear(wmWindow *win) { - GHOST_EndProgressBar(win->ghostwin); + GHOST_EndProgressBar(win->ghostwin); } /* ************************************ */ void wm_window_get_position(wmWindow *win, int *r_pos_x, int *r_pos_y) { - *r_pos_x = win->posx; - *r_pos_y = win->posy; + *r_pos_x = win->posx; + *r_pos_y = win->posy; } void wm_window_set_size(wmWindow *win, int width, int height) { - GHOST_SetClientSize(win->ghostwin, width, height); + GHOST_SetClientSize(win->ghostwin, width, height); } void wm_window_lower(wmWindow *win) { - GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderBottom); + GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderBottom); } void wm_window_raise(wmWindow *win) { - GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderTop); + GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderTop); } void wm_window_swap_buffers(wmWindow *win) { - GHOST_SwapWindowBuffers(win->ghostwin); + GHOST_SwapWindowBuffers(win->ghostwin); } -void wm_window_set_swap_interval (wmWindow *win, int interval) +void wm_window_set_swap_interval(wmWindow *win, int interval) { - GHOST_SetSwapInterval(win->ghostwin, interval); + GHOST_SetSwapInterval(win->ghostwin, interval); } bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut) { - return GHOST_GetSwapInterval(win->ghostwin, intervalOut); + return GHOST_GetSwapInterval(win->ghostwin, intervalOut); } - /* ******************* exported api ***************** */ - /* called whem no ghost system was initialized */ void WM_init_state_size_set(int stax, int stay, int sizx, int sizy) { - wm_init_state.start_x = stax; /* left hand pos */ - wm_init_state.start_y = stay; /* bottom pos */ - wm_init_state.size_x = sizx < 640 ? 640 : sizx; - wm_init_state.size_y = sizy < 480 ? 480 : sizy; - wm_init_state.override_flag |= WIN_OVERRIDE_GEOM; + wm_init_state.start_x = stax; /* left hand pos */ + wm_init_state.start_y = stay; /* bottom pos */ + wm_init_state.size_x = sizx < 640 ? 640 : sizx; + wm_init_state.size_y = sizy < 480 ? 480 : sizy; + wm_init_state.override_flag |= WIN_OVERRIDE_GEOM; } /* for borderless and border windows set from command-line */ void WM_init_state_fullscreen_set(void) { - wm_init_state.windowstate = GHOST_kWindowStateFullScreen; - wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE; + wm_init_state.windowstate = GHOST_kWindowStateFullScreen; + wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE; } void WM_init_state_normal_set(void) { - wm_init_state.windowstate = GHOST_kWindowStateNormal; - wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE; + wm_init_state.windowstate = GHOST_kWindowStateNormal; + wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE; } void WM_init_state_maximized_set(void) { - wm_init_state.windowstate = GHOST_kWindowStateMaximized; - wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE; + wm_init_state.windowstate = GHOST_kWindowStateMaximized; + wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE; } void WM_init_window_focus_set(bool do_it) { - wm_init_state.window_focus = do_it; + wm_init_state.window_focus = do_it; } void WM_init_native_pixels(bool do_it) { - wm_init_state.native_pixels = do_it; + wm_init_state.native_pixels = do_it; } void WM_init_tablet_api(void) { - if (g_system) { - switch (U.tablet_api) { - case USER_TABLET_NATIVE: - GHOST_SetTabletAPI(g_system, GHOST_kTabletNative); - break; - case USER_TABLET_WINTAB: - GHOST_SetTabletAPI(g_system, GHOST_kTabletWintab); - break; - case USER_TABLET_AUTOMATIC: - default: - GHOST_SetTabletAPI(g_system, GHOST_kTabletAutomatic); - break; - } - } + if (g_system) { + switch (U.tablet_api) { + case USER_TABLET_NATIVE: + GHOST_SetTabletAPI(g_system, GHOST_kTabletNative); + break; + case USER_TABLET_WINTAB: + GHOST_SetTabletAPI(g_system, GHOST_kTabletWintab); + break; + case USER_TABLET_AUTOMATIC: + default: + GHOST_SetTabletAPI(g_system, GHOST_kTabletAutomatic); + break; + } + } } /* This function requires access to the GHOST_SystemHandle (g_system) */ void WM_cursor_warp(wmWindow *win, int x, int y) { - if (win && win->ghostwin) { - int oldx = x, oldy = y; + if (win && win->ghostwin) { + int oldx = x, oldy = y; - wm_cursor_position_to_ghost(win, &x, &y); - GHOST_SetCursorPosition(g_system, x, y); + wm_cursor_position_to_ghost(win, &x, &y); + GHOST_SetCursorPosition(g_system, x, y); - win->eventstate->prevx = oldx; - win->eventstate->prevy = oldy; + win->eventstate->prevx = oldx; + win->eventstate->prevy = oldy; - win->eventstate->x = oldx; - win->eventstate->y = oldy; - } + win->eventstate->x = oldx; + win->eventstate->y = oldy; + } } /** @@ -2055,11 +2096,11 @@ void WM_cursor_warp(wmWindow *win, int x, int y) */ void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y) { - float f = GHOST_GetNativePixelSize(win->ghostwin); - if (f != 1.0f) { - *x = (int)(*x / f) * f; - *y = (int)(*y / f) * f; - } + float f = GHOST_GetNativePixelSize(win->ghostwin); + if (f != 1.0f) { + *x = (int)(*x / f) * f; + *y = (int)(*y / f) * f; + } } /** @@ -2067,29 +2108,29 @@ void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y) */ float WM_cursor_pressure(const struct wmWindow *win) { - const GHOST_TabletData *td = GHOST_GetTabletData(win->ghostwin); - /* if there's tablet data from an active tablet device then add it */ - if ((td != NULL) && td->Active != GHOST_kTabletModeNone) { - return wm_pressure_curve(td->Pressure); - } - else { - return -1.0f; - } + const GHOST_TabletData *td = GHOST_GetTabletData(win->ghostwin); + /* if there's tablet data from an active tablet device then add it */ + if ((td != NULL) && td->Active != GHOST_kTabletModeNone) { + return wm_pressure_curve(td->Pressure); + } + else { + return -1.0f; + } } /* support for native pixel size */ /* mac retina opens window in size X, but it has up to 2 x more pixels */ int WM_window_pixels_x(const wmWindow *win) { - float f = GHOST_GetNativePixelSize(win->ghostwin); + float f = GHOST_GetNativePixelSize(win->ghostwin); - return (int)(f * (float)win->sizex); + return (int)(f * (float)win->sizex); } int WM_window_pixels_y(const wmWindow *win) { - float f = GHOST_GetNativePixelSize(win->ghostwin); + float f = GHOST_GetNativePixelSize(win->ghostwin); - return (int)(f * (float)win->sizey); + return (int)(f * (float)win->sizey); } /** @@ -2097,7 +2138,7 @@ int WM_window_pixels_y(const wmWindow *win) */ void WM_window_rect_calc(const wmWindow *win, rcti *r_rect) { - BLI_rcti_init(r_rect, 0, WM_window_pixels_x(win), 0, WM_window_pixels_y(win)); + BLI_rcti_init(r_rect, 0, WM_window_pixels_x(win), 0, WM_window_pixels_y(win)); } /** * Get boundaries usable by screen-layouts, excluding global areas. @@ -2105,52 +2146,53 @@ void WM_window_rect_calc(const wmWindow *win, rcti *r_rect) */ void WM_window_screen_rect_calc(const wmWindow *win, rcti *r_rect) { - rcti window_rect, screen_rect; - - WM_window_rect_calc(win, &window_rect); - screen_rect = window_rect; - - /* Subtract global areas from screen rectangle. */ - for (ScrArea *global_area = win->global_areas.areabase.first; global_area; global_area = global_area->next) { - int height = ED_area_global_size_y(global_area) - 1; - - if (global_area->global->flag & GLOBAL_AREA_IS_HIDDEN) { - continue; - } - - switch (global_area->global->align) { - case GLOBAL_AREA_ALIGN_TOP: - if ((screen_rect.ymax - height) > window_rect.ymin) { - height += U.pixelsize; - } - if (screen_rect.ymax < (window_rect.ymax - 1)) { - height += U.pixelsize; - } - screen_rect.ymax -= height; - break; - case GLOBAL_AREA_ALIGN_BOTTOM: - if (screen_rect.ymin > window_rect.ymin) { - height += U.pixelsize; - } - if ((screen_rect.ymin + height) < (window_rect.ymax - 1)) { - height += U.pixelsize; - } - screen_rect.ymin += height; - break; - default: - BLI_assert(0); - break; - } - } - - BLI_assert(screen_rect.xmin < screen_rect.xmax); - BLI_assert(screen_rect.ymin < screen_rect.ymax); - *r_rect = screen_rect; + rcti window_rect, screen_rect; + + WM_window_rect_calc(win, &window_rect); + screen_rect = window_rect; + + /* Subtract global areas from screen rectangle. */ + for (ScrArea *global_area = win->global_areas.areabase.first; global_area; + global_area = global_area->next) { + int height = ED_area_global_size_y(global_area) - 1; + + if (global_area->global->flag & GLOBAL_AREA_IS_HIDDEN) { + continue; + } + + switch (global_area->global->align) { + case GLOBAL_AREA_ALIGN_TOP: + if ((screen_rect.ymax - height) > window_rect.ymin) { + height += U.pixelsize; + } + if (screen_rect.ymax < (window_rect.ymax - 1)) { + height += U.pixelsize; + } + screen_rect.ymax -= height; + break; + case GLOBAL_AREA_ALIGN_BOTTOM: + if (screen_rect.ymin > window_rect.ymin) { + height += U.pixelsize; + } + if ((screen_rect.ymin + height) < (window_rect.ymax - 1)) { + height += U.pixelsize; + } + screen_rect.ymin += height; + break; + default: + BLI_assert(0); + break; + } + } + + BLI_assert(screen_rect.xmin < screen_rect.xmax); + BLI_assert(screen_rect.ymin < screen_rect.ymax); + *r_rect = screen_rect; } bool WM_window_is_fullscreen(wmWindow *win) { - return win->windowstate == GHOST_kWindowStateFullScreen; + return win->windowstate == GHOST_kWindowStateFullScreen; } /** @@ -2159,37 +2201,37 @@ bool WM_window_is_fullscreen(wmWindow *win) */ void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene) { - for (wmWindow *win = win_lb->first; win; win = win->next) { - if (WM_window_get_active_scene(win) == scene) { - ED_workspace_scene_data_sync(win->workspace_hook, scene); - } - } + for (wmWindow *win = win_lb->first; win; win = win->next) { + if (WM_window_get_active_scene(win) == scene) { + ED_workspace_scene_data_sync(win->workspace_hook, scene); + } + } } Scene *WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen *screen) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (WM_window_get_active_screen(win) == screen) { - return WM_window_get_active_scene(win); - } - } + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (WM_window_get_active_screen(win) == screen) { + return WM_window_get_active_scene(win); + } + } - return NULL; + return NULL; } WorkSpace *WM_windows_workspace_get_from_screen(const wmWindowManager *wm, const bScreen *screen) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { - if (WM_window_get_active_screen(win) == screen) { - return WM_window_get_active_workspace(win); - } - } - return NULL; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (WM_window_get_active_screen(win) == screen) { + return WM_window_get_active_workspace(win); + } + } + return NULL; } Scene *WM_window_get_active_scene(const wmWindow *win) { - return win->scene; + return win->scene; } /** @@ -2197,114 +2239,114 @@ Scene *WM_window_get_active_scene(const wmWindow *win) */ void WM_window_set_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win_parent = (win->parent) ? win->parent : win; - bool changed = false; + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win_parent = (win->parent) ? win->parent : win; + bool changed = false; - /* Set scene in parent and its child windows. */ - if (win_parent->scene != scene) { - ED_screen_scene_change(C, win_parent, scene); - changed = true; - } + /* Set scene in parent and its child windows. */ + if (win_parent->scene != scene) { + ED_screen_scene_change(C, win_parent, scene); + changed = true; + } - for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { - if (win_child->parent == win_parent && win_child->scene != scene) { - ED_screen_scene_change(C, win_child, scene); - changed = true; - } - } + for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { + if (win_child->parent == win_parent && win_child->scene != scene) { + ED_screen_scene_change(C, win_child, scene); + changed = true; + } + } - if (changed) { - /* Update depsgraph and renderers for scene change. */ - ViewLayer *view_layer = WM_window_get_active_view_layer(win_parent); - ED_scene_change_update(bmain, scene, view_layer); + if (changed) { + /* Update depsgraph and renderers for scene change. */ + ViewLayer *view_layer = WM_window_get_active_view_layer(win_parent); + ED_scene_change_update(bmain, scene, view_layer); - /* Complete redraw. */ - WM_event_add_notifier(C, NC_WINDOW, NULL); - } + /* Complete redraw. */ + WM_event_add_notifier(C, NC_WINDOW, NULL); + } } ViewLayer *WM_window_get_active_view_layer(const wmWindow *win) { - Scene *scene = WM_window_get_active_scene(win); - if (scene == NULL) { - return NULL; - } + Scene *scene = WM_window_get_active_scene(win); + if (scene == NULL) { + return NULL; + } - ViewLayer *view_layer = BKE_view_layer_find(scene, win->view_layer_name); - if (view_layer) { - return view_layer; - } + ViewLayer *view_layer = BKE_view_layer_find(scene, win->view_layer_name); + if (view_layer) { + return view_layer; + } - view_layer = BKE_view_layer_default_view(scene); - if (view_layer) { - WM_window_set_active_view_layer((wmWindow *)win, view_layer); - } + view_layer = BKE_view_layer_default_view(scene); + if (view_layer) { + WM_window_set_active_view_layer((wmWindow *)win, view_layer); + } - return view_layer; + return view_layer; } void WM_window_set_active_view_layer(wmWindow *win, ViewLayer *view_layer) { - BLI_assert(BKE_view_layer_find(WM_window_get_active_scene(win), view_layer->name) != NULL); - Main *bmain = G_MAIN; + BLI_assert(BKE_view_layer_find(WM_window_get_active_scene(win), view_layer->name) != NULL); + Main *bmain = G_MAIN; - wmWindowManager *wm = bmain->wm.first; - wmWindow *win_parent = (win->parent) ? win->parent : win; + wmWindowManager *wm = bmain->wm.first; + wmWindow *win_parent = (win->parent) ? win->parent : win; - /* Set view layer in parent and child windows. */ - for (wmWindow *win_iter = wm->windows.first; win_iter; win_iter = win_iter->next) { - if ((win_iter == win_parent) || (win_iter->parent == win_parent)) { - STRNCPY(win_iter->view_layer_name, view_layer->name); - bScreen *screen = BKE_workspace_active_screen_get(win_iter->workspace_hook); - ED_render_view_layer_changed(bmain, screen); - } - } + /* Set view layer in parent and child windows. */ + for (wmWindow *win_iter = wm->windows.first; win_iter; win_iter = win_iter->next) { + if ((win_iter == win_parent) || (win_iter->parent == win_parent)) { + STRNCPY(win_iter->view_layer_name, view_layer->name); + bScreen *screen = BKE_workspace_active_screen_get(win_iter->workspace_hook); + ED_render_view_layer_changed(bmain, screen); + } + } } void WM_window_ensure_active_view_layer(wmWindow *win) { - /* Update layer name is correct after scene changes, load without UI, etc. */ - Scene *scene = WM_window_get_active_scene(win); + /* Update layer name is correct after scene changes, load without UI, etc. */ + Scene *scene = WM_window_get_active_scene(win); - if (scene && BKE_view_layer_find(scene, win->view_layer_name) == NULL) { - ViewLayer *view_layer = BKE_view_layer_default_view(scene); - STRNCPY(win->view_layer_name, view_layer->name); - } + if (scene && BKE_view_layer_find(scene, win->view_layer_name) == NULL) { + ViewLayer *view_layer = BKE_view_layer_default_view(scene); + STRNCPY(win->view_layer_name, view_layer->name); + } } WorkSpace *WM_window_get_active_workspace(const wmWindow *win) { - return BKE_workspace_active_get(win->workspace_hook); + return BKE_workspace_active_get(win->workspace_hook); } void WM_window_set_active_workspace(bContext *C, wmWindow *win, WorkSpace *workspace) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win_parent = (win->parent) ? win->parent : win; + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win_parent = (win->parent) ? win->parent : win; - ED_workspace_change(workspace, C, wm, win); + ED_workspace_change(workspace, C, wm, win); - for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { - if (win_child->parent == win_parent) { - bScreen *screen = WM_window_get_active_screen(win_child); - /* Don't change temporary screens, they only serve a single purpose. */ - if (screen->temp) { - continue; - } - ED_workspace_change(workspace, C, wm, win_child); - } - } + for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { + if (win_child->parent == win_parent) { + bScreen *screen = WM_window_get_active_screen(win_child); + /* Don't change temporary screens, they only serve a single purpose. */ + if (screen->temp) { + continue; + } + ED_workspace_change(workspace, C, wm, win_child); + } + } } WorkSpaceLayout *WM_window_get_active_layout(const wmWindow *win) { - const WorkSpace *workspace = WM_window_get_active_workspace(win); - return (LIKELY(workspace != NULL) ? BKE_workspace_active_layout_get(win->workspace_hook) : NULL); + const WorkSpace *workspace = WM_window_get_active_workspace(win); + return (LIKELY(workspace != NULL) ? BKE_workspace_active_layout_get(win->workspace_hook) : NULL); } void WM_window_set_active_layout(wmWindow *win, WorkSpace *workspace, WorkSpaceLayout *layout) { - BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout); + BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout); } /** @@ -2312,67 +2354,66 @@ void WM_window_set_active_layout(wmWindow *win, WorkSpace *workspace, WorkSpaceL */ bScreen *WM_window_get_active_screen(const wmWindow *win) { - const WorkSpace *workspace = WM_window_get_active_workspace(win); - /* May be NULL in rare cases like closing Blender */ - return (LIKELY(workspace != NULL) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL); + const WorkSpace *workspace = WM_window_get_active_workspace(win); + /* May be NULL in rare cases like closing Blender */ + return (LIKELY(workspace != NULL) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL); } void WM_window_set_active_screen(wmWindow *win, WorkSpace *workspace, bScreen *screen) { - BKE_workspace_active_screen_set(win->workspace_hook, workspace, screen); + BKE_workspace_active_screen_set(win->workspace_hook, workspace, screen); } bool WM_window_is_temp_screen(const wmWindow *win) { - const bScreen *screen = WM_window_get_active_screen(win); - return (screen && screen->temp != 0); + const bScreen *screen = WM_window_get_active_screen(win); + return (screen && screen->temp != 0); } - #ifdef WITH_INPUT_IME /* note: keep in mind wm_window_IME_begin is also used to reposition the IME window */ void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complete) { - BLI_assert(win); + BLI_assert(win); - GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete); + GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete); } void wm_window_IME_end(wmWindow *win) { - BLI_assert(win && win->ime_data); + BLI_assert(win && win->ime_data); - GHOST_EndIME(win->ghostwin); - win->ime_data = NULL; + GHOST_EndIME(win->ghostwin); + win->ime_data = NULL; } -#endif /* WITH_INPUT_IME */ +#endif /* WITH_INPUT_IME */ /* ****** direct opengl context management ****** */ void *WM_opengl_context_create(void) { - /* On Windows there is a problem creating contexts that share lists - * from one context that is current in another thread. - * So we should call this function only on the main thread. - */ - BLI_assert(BLI_thread_is_main()); - BLI_assert(GPU_framebuffer_active_get() == NULL); - return GHOST_CreateOpenGLContext(g_system); + /* On Windows there is a problem creating contexts that share lists + * from one context that is current in another thread. + * So we should call this function only on the main thread. + */ + BLI_assert(BLI_thread_is_main()); + BLI_assert(GPU_framebuffer_active_get() == NULL); + return GHOST_CreateOpenGLContext(g_system); } void WM_opengl_context_dispose(void *context) { - BLI_assert(GPU_framebuffer_active_get() == NULL); - GHOST_DisposeOpenGLContext(g_system, (GHOST_ContextHandle)context); + BLI_assert(GPU_framebuffer_active_get() == NULL); + GHOST_DisposeOpenGLContext(g_system, (GHOST_ContextHandle)context); } void WM_opengl_context_activate(void *context) { - BLI_assert(GPU_framebuffer_active_get() == NULL); - GHOST_ActivateOpenGLContext((GHOST_ContextHandle)context); + BLI_assert(GPU_framebuffer_active_get() == NULL); + GHOST_ActivateOpenGLContext((GHOST_ContextHandle)context); } void WM_opengl_context_release(void *context) { - BLI_assert(GPU_framebuffer_active_get() == NULL); - GHOST_ReleaseOpenGLContext((GHOST_ContextHandle)context); + BLI_assert(GPU_framebuffer_active_get() == NULL); + GHOST_ReleaseOpenGLContext((GHOST_ContextHandle)context); } |