diff options
77 files changed, 1753 insertions, 337 deletions
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index e26013c1ecd..9bb8def00d0 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -204,6 +204,7 @@ typedef enum { GHOST_kStandardCursorTopRightCorner, GHOST_kStandardCursorBottomRightCorner, GHOST_kStandardCursorBottomLeftCorner, + GHOST_kStandardCursorCopy, GHOST_kStandardCursorCustom, GHOST_kStandardCursorNumCursors, GHOST_kStandardCursorPencil diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index d8bb903dbe7..5d28e942655 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -1002,6 +1002,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, case GHOST_kEventWindowUpdate: pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); break; + case GHOST_kEventWindowMove: + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) ); + break; case GHOST_kEventWindowSize: if (!m_ignoreWindowSizedMessages) { diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp index 3e53a052146..8dae43ffd65 100644 --- a/intern/ghost/intern/GHOST_WindowCarbon.cpp +++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp @@ -635,6 +635,7 @@ void GHOST_WindowCarbon::loadCursor(bool visible, GHOST_TStandardCursor cursor) GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor); GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor); GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorCopy, kThemeCopyArrowCursor); }; #undef GCMAP diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 66c6d75b6d7..9c35786c791 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -72,6 +72,8 @@ extern "C" { - (void)windowDidResignKey:(NSNotification *)notification; - (void)windowDidExpose:(NSNotification *)notification; - (void)windowDidResize:(NSNotification *)notification; +- (void)windowDidMove:(NSNotification *)notification; +- (void)windowWillMove:(NSNotification *)notification; @end @implementation CocoaWindowDelegate : NSObject @@ -101,6 +103,16 @@ extern "C" { systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow); } +- (void)windowDidMove:(NSNotification *)notification +{ + systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow); +} + +- (void)windowWillMove:(NSNotification *)notification +{ + systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow); +} + - (void)windowDidResize:(NSNotification *)notification { #ifdef MAC_OS_X_VERSION_10_6 @@ -1042,6 +1054,7 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c case GHOST_kStandardCursorTopRightCorner: case GHOST_kStandardCursorBottomRightCorner: case GHOST_kStandardCursorBottomLeftCorner: + case GHOST_kStandardCursorCopy: case GHOST_kStandardCursorDefault: default: tmpCursor = [NSCursor arrowCursor]; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 16430c7c1b9..22045378e88 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -821,6 +821,7 @@ void GHOST_WindowWin32::loadCursor(bool visible, GHOST_TStandardCursor cursor) c case GHOST_kStandardCursorBottomRightCorner: id = IDC_SIZENWSE; break; case GHOST_kStandardCursorBottomLeftCorner: id = IDC_SIZENESW; break; case GHOST_kStandardCursorPencil: id = IDC_ARROW; break; + case GHOST_kStandardCursorCopy: id = IDC_ARROW; break; default: success = false; } diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 6c15d5d4e32..1e33f72f687 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1359,6 +1359,7 @@ getStandardCursor( GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break; GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break; GtoX(GHOST_kStandardCursorPencil, XC_pencil); break; + GtoX(GHOST_kStandardCursorCopy, XC_arrow); break; default: xcursor_id = 0; } diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 21150af7144..3a0cbd9d872 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -84,6 +84,8 @@ typedef struct SpaceType { void (*operatortypes)(void); /* add default items to WM keymap */ void (*keymap)(struct wmKeyConfig *); + /* on startup, define dropboxes for spacetype+regions */ + void (*dropboxes)(void); /* return context data */ int (*context)(const struct bContext *, const char*, struct bContextDataResult *); @@ -93,7 +95,7 @@ typedef struct SpaceType { /* tool shelf definitions */ ListBase toolshelf; - + /* read and write... */ /* default keymaps to add */ @@ -142,6 +144,8 @@ typedef struct ARegionType { /* hardcoded constraints, smaller than these values region is not visible */ int minsizex, minsizey; + /* when new region opens (region prefsizex/y are zero then */ + int prefsizex, prefsizey; /* default keymaps to add */ int keymapflag; } ARegionType; diff --git a/source/blender/blenlib/BLI_storage_types.h b/source/blender/blenlib/BLI_storage_types.h index 36d96f6075c..9ae7527253e 100644 --- a/source/blender/blenlib/BLI_storage_types.h +++ b/source/blender/blenlib/BLI_storage_types.h @@ -55,6 +55,7 @@ struct direntry{ char *string; mode_t type; char *relname; + char *path; #if (defined(WIN32) || defined(WIN64)) && (_MSC_VER>=1500) struct _stat64 s; #else diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index fb345de72e9..5ee97ff516b 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -66,6 +66,14 @@ char *BLI_strdupn(const char *str, int len); * the size of dst) * @retval Returns dst */ +char *BLI_strdupcat(const char *str1, const char *str2); + + /** + * Appends the two strings, and returns new mallocN'ed string + * @param str1 first string for copy + * @param str2 second string for append + * @retval Returns dst + */ char *BLI_strncpy(char *dst, const char *src, int maxncpy); /* Makes a copy of the text within the "" that appear after some text 'blahblah' diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 09bca168e64..ee7734fb14b 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -261,6 +261,7 @@ void BLI_builddir(char *dirname, char *relname) while(dlink){ memset(&files[actnum], 0 , sizeof(struct direntry)); files[actnum].relname = dlink->name; + files[actnum].path = BLI_strdupcat(dirname, dlink->name); // use 64 bit file size, only needed for WIN32 and WIN64. // Excluding other than current MSVC compiler until able to test. #if (defined(WIN32) || defined(WIN64)) && (_MSC_VER>=1500) diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 405f8c6db97..e60209281a7 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -54,6 +54,19 @@ char *BLI_strdup(const char *str) { return BLI_strdupn(str, strlen(str)); } +char *BLI_strdupcat(const char *str1, const char *str2) +{ + int len; + char *n; + + len= strlen(str1)+strlen(str2); + n= MEM_mallocN(len+1, "strdupcat"); + strcpy(n, str1); + strcat(n, str2); + + return n; +} + char *BLI_strncpy(char *dst, const char *src, int maxncpy) { int srclen= strlen(src); int cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 1309c0b3bf1..26eafa38f8e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4536,6 +4536,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) wm->defaultconf= NULL; wm->jobs.first= wm->jobs.last= NULL; + wm->drags.first= wm->drags.last= NULL; wm->windrawable= NULL; wm->initialized= 0; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index a7879c7b70d..b2ce1c76f83 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -159,5 +159,7 @@ void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct AR void view3d_clipping_local(struct RegionView3D *rv3d, float mat[][4]); +Base *ED_view3d_give_base_under_cursor(struct bContext *C, short *mval); + #endif /* ED_VIEW3D_H */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 517a1e92f93..309cee7cb9c 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -61,6 +61,7 @@ struct ImageUser; struct uiWidgetColors; struct Tex; struct MTex; +struct ImBuf; typedef struct uiBut uiBut; typedef struct uiBlock uiBlock; @@ -343,6 +344,15 @@ void uiBlockSetXOfs (uiBlock *block, int xofs); int uiButGetRetVal (uiBut *but); +void uiButSetDragID(uiBut *but, struct ID *id); +void uiButSetDragRNA(uiBut *but, struct PointerRNA *ptr); +void uiButSetDragPath(uiBut *but, const char *path); +void uiButSetDragName(uiBut *but, const char *name); +void uiButSetDragValue(uiBut *but); +void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale); + +int UI_but_active_drop_name(struct bContext *C); + void uiButSetFlag (uiBut *but, int flag); void uiButClearFlag (uiBut *but, int flag); @@ -700,6 +710,7 @@ void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *p void uiItemsFullEnumO(uiLayout *layout, char *opname, char *propname, struct IDProperty *properties, int context, int flag); void uiItemL(uiLayout *layout, char *name, int icon); /* label */ +void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, char *name, int icon); /* label icon for dragging */ void uiItemM(uiLayout *layout, struct bContext *C, char *name, int icon, char *menuname); /* menu */ void uiItemV(uiLayout *layout, char *name, int icon, int argval); /* value */ void uiItemS(uiLayout *layout); /* separator */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 47a65812197..44c943fa4f4 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2743,6 +2743,7 @@ uiBut *uiDefButO(uiBlock *block, int type, char *opname, int opcontext, char *st return but; } +/* if a1==1.0 then a2 is an extra icon blending factor (alpha 0.0 - 1.0) */ uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip) { uiBut *but= ui_def_but(block, type, retval, "", x1, y1, x2, y2, poin, min, max, a1, a2, tip); @@ -3014,6 +3015,45 @@ int uiButGetRetVal(uiBut *but) return but->retval; } +void uiButSetDragID(uiBut *but, ID *id) +{ + but->dragtype= WM_DRAG_ID; + but->dragpoin= (void *)id; +} + +void uiButSetDragRNA(uiBut *but, PointerRNA *ptr) +{ + but->dragtype= WM_DRAG_RNA; + but->dragpoin= (void *)ptr; +} + +void uiButSetDragPath(uiBut *but, const char *path) +{ + but->dragtype= WM_DRAG_PATH; + but->dragpoin= (void *)path; +} + +void uiButSetDragName(uiBut *but, const char *name) +{ + but->dragtype= WM_DRAG_NAME; + but->dragpoin= (void *)name; +} + +/* value from button itself */ +void uiButSetDragValue(uiBut *but) +{ + but->dragtype= WM_DRAG_VALUE; +} + +void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale) +{ + but->dragtype= WM_DRAG_PATH; + but->icon= icon; /* no flag UI_HAS_ICON, so icon doesnt draw in button */ + but->dragpoin= (void *)path; + but->imb= imb; + but->imb_scale= scale; +} + PointerRNA *uiButGetOperatorPtrRNA(uiBut *but) { if(but->optype && !but->opptr) { diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 090f5d38279..5363cf8937c 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -20,9 +20,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. + * Contributor(s): Blender Foundation * * ***** END GPL LICENSE BLOCK ***** */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 7273dc2360e..b84bdcd958e 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -89,6 +89,7 @@ typedef enum uiHandleButtonState { BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_TEXT_SELECTING, BUTTON_STATE_MENU_OPEN, + BUTTON_STATE_WAIT_DRAG, BUTTON_STATE_EXIT } uiHandleButtonState; @@ -602,6 +603,53 @@ static void ui_apply_but_CHARTAB(bContext *C, uiBut *but, uiHandleButtonData *da } #endif +/* ****************** drag drop code *********************** */ + +static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, wmEvent *event) +{ + rcti rect; + int x= event->x, y= event->y; + + ui_window_to_block(ar, but->block, &x, &y); + + rect.xmin= but->x1; rect.xmax= but->x2; + rect.ymin= but->y1; rect.ymax= but->y2; + + if(but->imb); /* use button size itself */ + else if(but->flag & UI_ICON_LEFT) { + rect.xmax= rect.xmin + (rect.ymax-rect.ymin); + } + else { + int delta= (rect.xmax-rect.xmin) - (rect.ymax-rect.ymin); + rect.xmin += delta/2; + rect.xmax -= delta/2; + } + + return BLI_in_rcti(&rect, x, y); +} + +#define UI_DRAG_THRESHOLD 3 +static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) +{ + /* prevent other WM gestures to start while we try to drag */ + WM_gestures_remove(C); + + if( ABS(data->dragstartx - event->x) + ABS(data->dragstarty - event->y) > UI_DRAG_THRESHOLD ) { + wmDrag *drag; + + button_activate_state(C, but, BUTTON_STATE_EXIT); + data->cancel= 1; + + drag= WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but)); + if(but->imb) + WM_event_drag_image(drag, but->imb, but->imb_scale, but->x2-but->x1, but->y2-but->y1); + return 1; + } + + return 0; +} + +/* ********************** linklines *********************** */ static void ui_delete_active_linkline(uiBlock *block) { @@ -894,6 +942,30 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut but->editcumap= editcumap; } +/* ******************* drop event ******************** */ + +/* only call if event type is EVT_DROP */ +static void ui_but_drop(bContext *C, wmEvent *event, uiBut *but, uiHandleButtonData *data) +{ + wmDrag *wmd; + ListBase *drags= event->customdata; /* drop event type has listbase customdata by default */ + + for(wmd= drags->first; wmd; wmd= wmd->next) { + if(wmd->type==WM_DRAG_ID) { + /* align these types with UI_but_active_drop_name */ + if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { + ID *id= (ID *)wmd->poin; + + if(but->poin==NULL && but->rnapoin.data==NULL); + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + BLI_strncpy(data->str, id->name+2, data->maxlen); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } + } + +} + /* ******************* copy and paste ******************** */ /* c = copy, v = paste */ @@ -1984,13 +2056,40 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) { + if(data->state == BUTTON_STATE_HIGHLIGHT) { + + /* first handle click on icondrag type button */ + if(event->type==LEFTMOUSE && but->dragpoin) { + if(ui_but_mouse_inside_icon(but, data->region, event)) { + button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); + data->dragstartx= event->x; + data->dragstarty= event->y; + return WM_UI_HANDLER_BREAK; + } + } + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } } - + else if(data->state == BUTTON_STATE_WAIT_DRAG) { + + /* this function also ends state */ + if(ui_but_start_drag(C, but, data, event)) { + return WM_UI_HANDLER_BREAK; + } + + /* pass on release as press for other keymaps XXX hack alert! */ + if(event->type==LEFTMOUSE && event->val==KM_RELEASE) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + event->val= KM_PRESS; + return WM_UI_HANDLER_CONTINUE; + } + + } + return WM_UI_HANDLER_CONTINUE; } @@ -2554,10 +2653,23 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut return retval; } + static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) { if(data->state == BUTTON_STATE_HIGHLIGHT) { + + /* first handle click on icondrag type button */ + if(event->type==LEFTMOUSE && but->dragpoin && event->val==KM_PRESS) { + if(ui_but_mouse_inside_icon(but, data->region, event)) { + button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); + data->dragstartx= event->x; + data->dragstarty= event->y; + return WM_UI_HANDLER_BREAK; + } + } + + /* regular open menu */ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); return WM_UI_HANDLER_BREAK; @@ -2598,6 +2710,26 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm } } } + else if(data->state == BUTTON_STATE_WAIT_DRAG) { + + /* this function also ends state */ + if(ui_but_start_drag(C, but, data, event)) { + return WM_UI_HANDLER_BREAK; + } + + /* outside icon quit, not needed if drag activated */ + if(0==ui_but_mouse_inside_icon(but, data->region, event)) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + data->cancel= 1; + return WM_UI_HANDLER_BREAK; + } + + if(event->type==LEFTMOUSE && event->val==KM_RELEASE) { + button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); + return WM_UI_HANDLER_BREAK; + } + + } return WM_UI_HANDLER_CONTINUE; } @@ -3747,6 +3879,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) ui_but_copy_paste(C, but, data, (event->type == CKEY)? 'c': 'v'); return WM_UI_HANDLER_BREAK; } + /* handle drop */ + else if(event->type == EVT_DROP) { + ui_but_drop (C, event, but, data); + } /* handle keyframing */ else if(event->type == IKEY && event->val == KM_PRESS) { if(event->alt) @@ -3931,6 +4067,21 @@ int ui_button_is_active(ARegion *ar) return (ui_but_find_activated(ar) != NULL); } +/* returns TRUE if highlighted button allows drop of names */ +/* called in region context */ +int UI_but_active_drop_name(bContext *C) +{ + ARegion *ar= CTX_wm_region(C); + uiBut *but= ui_but_find_activated(ar); + + if(but) { + if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) + return 1; + } + + return 0; +} + static void ui_blocks_set_tooltips(ARegion *ar, int enable) { uiBlock *block; @@ -4018,8 +4169,8 @@ static uiBut *ui_but_find_mouse_over(wmWindow *win, ARegion *ar, int x, int y) uiBut *but, *butover= NULL; int mx, my; - if(!win->active) - return NULL; +// if(!win->active) +// return NULL; if(!ui_mouse_inside_region(ar, x, y)) return NULL; @@ -4029,7 +4180,10 @@ static uiBut *ui_but_find_mouse_over(wmWindow *win, ARegion *ar, int x, int y) ui_window_to_block(ar, block, &mx, &my); for(but=block->buttons.first; but; but= but->next) { - if(ELEM4(but->type, LABEL, ROUNDBOX, SEPR, LISTBOX)) + /* note, LABEL is included for hilights, this allows drags */ + if(but->type==LABEL && but->dragpoin==NULL) + continue; + if(ELEM3(but->type, ROUNDBOX, SEPR, LISTBOX)) continue; if(but->flag & UI_HIDDEN) continue; @@ -4047,8 +4201,8 @@ static uiBut *ui_list_find_mouse_over(wmWindow *win, ARegion *ar, int x, int y) uiBut *but; int mx, my; - if(!win->active) - return NULL; +// if(!win->active) +// return NULL; if(!ui_mouse_inside_region(ar, x, y)) return NULL; @@ -4095,8 +4249,9 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but) } } -static void button_tooltip_timer_reset(uiBut *but) +static void button_tooltip_timer_reset(bContext *C, uiBut *but) { + wmWindowManager *wm= CTX_wm_manager(C); uiHandleButtonData *data; data= but->active; @@ -4108,7 +4263,8 @@ static void button_tooltip_timer_reset(uiBut *but) if(U.flag & USER_TOOLTIPS) if(!but->block->tooltipdisabled) - data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY); + if(!wm->drags.first) + data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY); } static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state) @@ -4123,7 +4279,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s if(state == BUTTON_STATE_HIGHLIGHT) { but->flag &= ~UI_SELECT; - button_tooltip_timer_reset(but); + button_tooltip_timer_reset(C, but); /* automatic open pulldown block timer */ if(ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) { @@ -4190,6 +4346,11 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s WM_event_remove_ui_handler(&data->window->modalhandlers, ui_handler_region_menu, NULL, data); } } + + /* wait for mousemove to enable drag */ + if(state == BUTTON_STATE_WAIT_DRAG) { + but->flag &= ~UI_SELECT; + } data->state= state; @@ -4449,7 +4610,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) else if(event->x!=event->prevx || event->y!=event->prevy) { /* re-enable tooltip on mouse move */ ui_blocks_set_tooltips(ar, 1); - button_tooltip_timer_reset(but); + button_tooltip_timer_reset(C, but); } break; @@ -4555,8 +4716,8 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) retval= WM_UI_HANDLER_CONTINUE; } else { - ui_do_button(C, block, but, event); - retval= WM_UI_HANDLER_BREAK; + retval= ui_do_button(C, block, but, event); + // retval= WM_UI_HANDLER_BREAK; XXX why ? } if(data->state == BUTTON_STATE_EXIT) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 296b1e3ca57..6c4f5564fd7 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -613,6 +613,7 @@ static void init_iconfile_list(struct ListBase *list) for(; i>=0; i--){ MEM_freeN(dir[i].relname); + MEM_freeN(dir[i].path); if (dir[i].string) MEM_freeN(dir[i].string); } free(dir); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index cd89650d750..47892e45a02 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -46,6 +46,7 @@ struct uiLayout; struct bContextStore; struct Scene; struct ID; +struct ImBuf; /* ****************** general defines ************** */ @@ -226,8 +227,14 @@ struct uiBut { int opcontext; struct IDProperty *opproperties; struct PointerRNA *opptr; + + /* Draggable data, type is WM_DRAG_... */ + int dragtype; + void *dragpoin; + struct ImBuf *imb; + float imb_scale; - /* active button data */ + /* active button data */ struct uiHandleButtonData *active; char *editstr; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 57102f4ad50..52ea0a99762 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1321,7 +1321,7 @@ void uiItemM(uiLayout *layout, bContext *C, char *name, int icon, char *menuname } /* label item */ -void uiItemL(uiLayout *layout, char *name, int icon) +static uiBut *uiItemL_(uiLayout *layout, char *name, int icon) { uiBlock *block= layout->root->block; uiBut *but; @@ -1342,8 +1342,25 @@ void uiItemL(uiLayout *layout, char *name, int icon) but= uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); else but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + + return but; +} + +void uiItemL(uiLayout *layout, char *name, int icon) +{ + uiItemL_(layout, name, icon); +} + +void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, char *name, int icon) +{ + uiBut *but= uiItemL_(layout, name, icon); + + if(ptr && ptr->type) + if(RNA_struct_is_ID(ptr->type)) + uiButSetDragID(but, ptr->id.data); } + /* value item */ void uiItemV(uiLayout *layout, char *name, int icon, int argval) { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a90ddd991ca..264bc724bce 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -360,8 +360,9 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, "Browse ID data"); if(type) { but->icon= RNA_struct_ui_icon(type); - but->flag|= UI_HAS_ICON; - but->flag|= UI_ICON_LEFT; + /* default dragging of icon for id browse buttons */ + uiButSetDragID(but, id); + uiButSetFlag(but, UI_HAS_ICON|UI_ICON_LEFT); } if((idfrom && idfrom->lib)) @@ -2215,7 +2216,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiBlockSetEmboss(block, UI_EMBOSS); } else - uiItemL(sub, name, icon); + uiItemLDrag(sub, itemptr, name, icon); /* fails, backdrop LISTROW... */ /* free name */ if(namebuf) @@ -2299,6 +2300,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propna icon= list_item_icon_get(C, &itemptr, rnaicon); but= uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); + i++; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index a3c754c10e5..d9e8f6f55d2 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -755,6 +755,9 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect else alpha= 0.5f; } + /* extra feature allows more alpha blending */ + if(but->type==LABEL && but->a1==1.0f) alpha *= but->a2; + glEnable(GL_BLEND); if(icon && icon!=ICON_BLANK1) { @@ -784,8 +787,14 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect xs= (rect->xmin+rect->xmax- height)/2; ys= (rect->ymin+rect->ymax- height)/2; } - - UI_icon_draw_aspect(xs, ys, icon, aspect, alpha); + + /* to indicate draggable */ + if(but->dragpoin && (but->flag & UI_ACTIVE)) { + float rgb[3]= {1.25f, 1.25f, 1.25f}; + UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb); + } + else + UI_icon_draw_aspect(xs, ys, icon, aspect, alpha); } if(but->flag & UI_ICON_SUBMENU) { diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 050152821f5..90764388029 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -46,6 +46,7 @@ #include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_global.h" +#include "BKE_library.h" #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_report.h" @@ -62,6 +63,7 @@ #include "ED_mesh.h" #include "ED_object.h" +#include "ED_uvedit.h" #include "ED_view3d.h" #include "RE_render_ext.h" @@ -309,6 +311,68 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Scene *scene= CTX_data_scene(C); + Base *base= ED_view3d_give_base_under_cursor(C, event->mval); + Image *ima; + Mesh *me; + Object *obedit; + int exitmode= 0; + char name[32]; + + /* check input variables */ + RNA_string_get(op->ptr, "name", name); + ima= (Image *)find_id("IM", name); + if(base==NULL || base->object->type!=OB_MESH || ima==NULL) { + BKE_report(op->reports, RPT_ERROR, "Not a Mesh or no Image."); + return OPERATOR_CANCELLED; + } + + /* turn mesh in editmode */ + /* BKE_mesh_get/end_editmesh: ED_uvedit_assign_image also calls this */ + + obedit= base->object; + me= obedit->data; + if(me->edit_mesh==NULL) { + make_editMesh(scene, obedit); + exitmode= 1; + } + if(me->edit_mesh==NULL) + return OPERATOR_CANCELLED; + + ED_uvedit_assign_image(scene, obedit, ima, NULL); + + if(exitmode) { + load_editMesh(scene, obedit); + free_editMesh(me->edit_mesh); + MEM_freeN(me->edit_mesh); + me->edit_mesh= NULL; + } + + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_drop_named_image(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Assign Image to UV Texture"; + ot->description= "Assigns Image to active UV layer, or creates a UV layer"; + ot->idname= "MESH_OT_drop_named_image"; + + /* api callbacks */ + ot->poll= layers_poll; + ot->invoke= drop_named_image_invoke; + + /* flags */ + ot->flag= OPTYPE_UNDO; + + /* properties */ + RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Image name to assign."); +} + static int uv_texture_remove_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index d06ad8cd384..950da02b50d 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -234,7 +234,7 @@ void MESH_OT_rip(struct wmOperatorType *ot); void MESH_OT_shape_propagate_to_all(struct wmOperatorType *ot); void MESH_OT_blend_from_shape(struct wmOperatorType *ot); -/* ******************* mesh_layers.c */ +/* ******************* mesh_data.c */ void MESH_OT_uv_texture_add(struct wmOperatorType *ot); void MESH_OT_uv_texture_remove(struct wmOperatorType *ot); @@ -242,6 +242,7 @@ void MESH_OT_vertex_color_add(struct wmOperatorType *ot); void MESH_OT_vertex_color_remove(struct wmOperatorType *ot); void MESH_OT_sticky_add(struct wmOperatorType *ot); void MESH_OT_sticky_remove(struct wmOperatorType *ot); +void MESH_OT_drop_named_image(struct wmOperatorType *ot); void MESH_OT_edgering_select(struct wmOperatorType *ot); void MESH_OT_loopcut(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index d3e639be9d3..c3bb8dd061d 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -147,7 +147,8 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_vertex_color_remove); WM_operatortype_append(MESH_OT_sticky_add); WM_operatortype_append(MESH_OT_sticky_remove); - + WM_operatortype_append(MESH_OT_drop_named_image); + WM_operatortype_append(MESH_OT_edgering_select); WM_operatortype_append(MESH_OT_loopcut); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index ee88a192e0a..dea8b13e9cc 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1693,6 +1693,70 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX); } +/* **************** add named object, for dragdrop ************* */ + +/* contextual operator dupli */ +static int add_named_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Base *basen, *base; + Object *ob; + int linked= RNA_boolean_get(op->ptr, "linked"); + int dupflag= (linked)? 0: U.dupflag; + char name[32]; + + /* find object, create fake base */ + RNA_string_get(op->ptr, "name", name); + ob= (Object *)find_id("OB", name); + if(ob==NULL) + return OPERATOR_CANCELLED; + + base= MEM_callocN(sizeof(Base), "duplibase"); + base->object= ob; + base->flag= ob->flag; + + /* prepare dupli */ + clear_id_newpoins(); + clear_sca_new_poins(); /* sensor/contr/act */ + + basen= object_add_duplicate_internal(scene, base, dupflag); + basen->lay= basen->object->lay= scene->lay; + + ED_object_location_from_view(C, basen->object->loc); + ED_base_object_activate(C, basen); + + copy_object_set_idnew(C, dupflag); + + DAG_scene_sort(scene); + DAG_ids_flush_update(0); + + MEM_freeN(base); + + WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_add_named(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Named Object"; + ot->description = "Add named object."; + ot->idname= "OBJECT_OT_add_named"; + + /* api callbacks */ + ot->exec= add_named_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data."); + RNA_def_string(ot->srna, "name", "Cube", 24, "Name", "Object name to add."); +} + + + /**************************** Join *************************/ static int join_poll(bContext *C) { diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index a11ead1fe9d..06768404d7e 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -69,6 +69,7 @@ void OBJECT_OT_make_single_user(struct wmOperatorType *ot); void OBJECT_OT_make_links_scene(struct wmOperatorType *ot); void OBJECT_OT_make_links_data(struct wmOperatorType *ot); void OBJECT_OT_move_to_layer(struct wmOperatorType *ot); +void OBJECT_OT_drop_named_material(struct wmOperatorType *ot); /* object_edit.c */ void OBJECT_OT_mode_set(struct wmOperatorType *ot); @@ -95,6 +96,7 @@ void OBJECT_OT_select_name(struct wmOperatorType *ot); /* object_add.c */ void OBJECT_OT_add(struct wmOperatorType *ot); +void OBJECT_OT_add_named(struct wmOperatorType *ot); void OBJECT_OT_curve_add(struct wmOperatorType *ot); void OBJECT_OT_surface_add(struct wmOperatorType *ot); void OBJECT_OT_metaball_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 80992887e97..b9935fafb74 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -121,6 +121,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_lamp_add); WM_operatortype_append(OBJECT_OT_camera_add); WM_operatortype_append(OBJECT_OT_add); + WM_operatortype_append(OBJECT_OT_add_named); WM_operatortype_append(OBJECT_OT_effector_add); WM_operatortype_append(OBJECT_OT_group_instance_add); WM_operatortype_append(OBJECT_OT_metaball_add); @@ -202,6 +203,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_hook_recenter); WM_operatortype_append(OBJECT_OT_bake_image); + WM_operatortype_append(OBJECT_OT_drop_named_material); } void ED_operatormacros_object(void) @@ -224,6 +226,15 @@ void ED_operatormacros_object(void) otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF); } + + /* XXX */ + ot= WM_operatortype_append_macro("OBJECT_OT_add_named_cursor", "Add named object at cursor", OPTYPE_UNDO|OPTYPE_REGISTER); + if(ot) { + RNA_def_string(ot->srna, "name", "Cube", 24, "Name", "Object name to add."); + + WM_operatortype_macro_define(ot, "VIEW3D_OT_cursor3d"); + WM_operatortype_macro_define(ot, "OBJECT_OT_add_named"); + } } static int object_mode_poll(bContext *C) @@ -308,7 +319,7 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move_linked", DKEY, KM_PRESS, KM_ALT, 0); - + WM_keymap_add_item(keymap, "OBJECT_OT_join", JKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "OBJECT_OT_convert", CKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_proxy_make", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 46b90725d7f..7f4100c01ed 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -91,6 +91,7 @@ #include "ED_curve.h" #include "ED_object.h" #include "ED_screen.h" +#include "ED_view3d.h" #include "object_intern.h" @@ -1827,3 +1828,41 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) RNA_def_boolean(ot->srna, "texture", 0, "Textures", "Make textures local to each material"); RNA_def_boolean(ot->srna, "animation", 0, "Animation Data", "Make animation data local to each object"); } + +static int drop_named_material_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Base *base= ED_view3d_give_base_under_cursor(C, event->mval); + Material *ma; + char name[32]; + + RNA_string_get(op->ptr, "name", name); + ma= (Material *)find_id("MA", name); + if(base==NULL || ma==NULL) + return OPERATOR_CANCELLED; + + assign_material(base->object, ma, 1); + + WM_event_add_notifier(C, NC_OBJECT|ND_SHADING, base->object); + return OPERATOR_FINISHED; +} + +/* used for dropbox */ +/* assigns to object under cursor, only first material slot */ +void OBJECT_OT_drop_named_material(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Drop Named Material on Object"; + ot->description = ""; + ot->idname= "OBJECT_OT_drop_named_material"; + + /* api callbacks */ + ot->invoke= drop_named_material_invoke; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_UNDO; + + /* properties */ + RNA_def_string(ot->srna, "name", "Material", 24, "Name", "Material name to assign."); +} diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index a7a3754d16f..93f6542f9cb 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -624,8 +624,8 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int if(ar->next==NULL && alignment!=RGN_ALIGN_QSPLIT) alignment= RGN_ALIGN_NONE; - prefsizex= ar->type->minsizex; - prefsizey= ar->type->minsizey; + prefsizex= ar->sizex?ar->sizex:ar->type->prefsizex; + prefsizey= ar->sizey?ar->sizey:ar->type->prefsizey; /* hidden is user flag */ if(ar->flag & RGN_FLAG_HIDDEN); @@ -1230,11 +1230,11 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, char *contex if(vertical) { w= v2d->cur.xmax - v2d->cur.xmin; - em= (ar->type->minsizex)? 10: 20; + em= (ar->type->prefsizex)? 10: 20; } else { w= UI_PANEL_WIDTH; - em= (ar->type->minsizex)? 10: 20; + em= (ar->type->prefsizex)? 10: 20; } x= 0; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 786f9ee9e3f..048ade764d5 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -468,6 +468,7 @@ static void screen_copy(bScreen *to, bScreen *from) sa->spacedata.first= sa->spacedata.last= NULL; sa->regionbase.first= sa->regionbase.last= NULL; sa->actionzones.first= sa->actionzones.last= NULL; + sa->handlers.first= sa->handlers.last= NULL; area_copy_data(sa, saf, 0); } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index bc9e7239f01..7f6f1c34760 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1384,10 +1384,18 @@ static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event) rmd->origx= event->x; rmd->origy= event->y; rmd->maxsize = area_max_regionsize(rmd->sa, rmd->ar, rmd->edge); + + /* if not set we do now, otherwise it uses type */ + if(rmd->ar->sizex==0) + rmd->ar->sizex= rmd->ar->type->prefsizex; + if(rmd->ar->sizey==0) + rmd->ar->sizey= rmd->ar->type->prefsizey; + + /* now copy to regionmovedata */ if(rmd->edge=='l' || rmd->edge=='r') { - rmd->origval= rmd->ar->type->minsizex; + rmd->origval= rmd->ar->sizex; } else { - rmd->origval= rmd->ar->type->minsizey; + rmd->origval= rmd->ar->sizey; } CLAMP(rmd->maxsize, 0, 1000); @@ -1413,11 +1421,11 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) delta= event->x - rmd->origx; if(rmd->edge=='l') delta= -delta; - rmd->ar->type->minsizex= rmd->origval + delta; - CLAMP(rmd->ar->type->minsizex, 0, rmd->maxsize); + rmd->ar->sizex= rmd->origval + delta; + CLAMP(rmd->ar->sizex, 0, rmd->maxsize); - if(rmd->ar->type->minsizex < 24) { - rmd->ar->type->minsizex= rmd->origval; + if(rmd->ar->sizex < 24) { + rmd->ar->sizex= rmd->origval; if(!(rmd->ar->flag & RGN_FLAG_HIDDEN)) ED_region_toggle_hidden(C, rmd->ar); } @@ -1428,11 +1436,11 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) delta= event->y - rmd->origy; if(rmd->edge=='b') delta= -delta; - rmd->ar->type->minsizey= rmd->origval + delta; - CLAMP(rmd->ar->type->minsizey, 0, rmd->maxsize); + rmd->ar->sizey= rmd->origval + delta; + CLAMP(rmd->ar->sizey, 0, rmd->maxsize); - if(rmd->ar->type->minsizey < 24) { - rmd->ar->type->minsizey= rmd->origval; + if(rmd->ar->sizey < 24) { + rmd->ar->sizey= rmd->origval; if(!(rmd->ar->flag & RGN_FLAG_HIDDEN)) ED_region_toggle_hidden(C, rmd->ar); } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 803a7aee8cc..26464dcfab8 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -475,7 +475,7 @@ void ED_spacetype_action(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype action region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->init= action_header_area_init; @@ -487,7 +487,7 @@ void ED_spacetype_action(void) /* regions: channels */ art= MEM_callocN(sizeof(ARegionType), "spacetype action region"); art->regionid = RGN_TYPE_CHANNELS; - art->minsizex= 200; + art->prefsizex= 200; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D; art->init= action_channel_area_init; diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index c1fec6cd1de..492080eda52 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -105,10 +105,12 @@ void ED_spacetypes_init(void) UI_view2d_operatortypes(); UI_buttons_operatortypes(); + /* register operators */ spacetypes = BKE_spacetypes_list(); - for(type=spacetypes->first; type; type=type->next) - type->operatortypes(); - + for(type=spacetypes->first; type; type=type->next) { + if(type->operatortypes) + type->operatortypes(); + } /* Macros's must go last since they reference other operators * maybe we'll need to have them go after python operators too? */ @@ -117,6 +119,14 @@ void ED_spacetypes_init(void) ED_operatormacros_node(); ED_operatormacros_object(); ED_operatormacros_file(); + + /* register dropboxes (can use macros) */ + spacetypes = BKE_spacetypes_list(); + for(type=spacetypes->first; type; type=type->next) { + if(type->dropboxes) + type->dropboxes(); + } + } /* called in wm.c */ diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 39990df34a7..d94170533cf 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -787,10 +787,10 @@ void buttons_context_draw(const bContext *C, uiLayout *layout) if(name) { if(!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE) && ptr->type == &RNA_Scene) - uiItemL(row, "", icon); /* save some space */ + uiItemLDrag(row, ptr, "", icon); /* save some space */ else - uiItemL(row, name, icon); - + uiItemLDrag(row, ptr, name, icon); + if(name != namebuf) MEM_freeN(name); } diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 17f5c6bf7c3..6f52a84ce80 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -396,7 +396,7 @@ void ED_spacetype_buttons(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype buttons region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= BUTS_HEADERY; + art->prefsizey= BUTS_HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->init= buttons_header_area_init; diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index e9e87a865ef..ea1d6667d11 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -366,7 +366,7 @@ void ED_spacetype_console(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype console region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_HEADER; art->init= console_header_area_init; diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index af0bf9413df..5db17d8bc7c 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -320,8 +320,9 @@ static int get_file_icon(struct direntry *file) return ICON_FILE_BLANK; } -static void file_draw_icon(int sx, int sy, int icon, int width, int height) +static void file_draw_icon(uiBlock *block, char *path, int sx, int sy, int icon, int width, int height) { + uiBut *but; float x,y; float alpha=1.0f; @@ -329,10 +330,9 @@ static void file_draw_icon(int sx, int sy, int icon, int width, int height) y = (float)(sy-height); if (icon == ICON_FILE_BLANK) alpha = 0.375f; - - glEnable(GL_BLEND); - - UI_icon_draw_aspect(x, y, icon, 1.f, alpha); + + but= uiDefIconBut(block, LABEL, 0, icon, x, y, width, height, NULL, 0.0, 0.0, 0, 0, ""); + uiButSetDragPath(but, path); } @@ -364,62 +364,67 @@ void file_calc_previews(const bContext *C, ARegion *ar) UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height+V2D_SCROLL_HEIGHT); } -static void file_draw_preview(int sx, int sy, ImBuf *imb, FileLayout *layout, short dropshadow) +static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int sy, ImBuf *imb, FileLayout *layout, short dropshadow) { if (imb) { - float fx, fy; - float dx, dy; - int xco, yco; - float scaledx, scaledy; - float scale; - int ex, ey; - - if ( (imb->x > layout->prv_w) || (imb->y > layout->prv_h) ) { - if (imb->x > imb->y) { - scaledx = (float)layout->prv_w; - scaledy = ( (float)imb->y/(float)imb->x )*layout->prv_w; - scale = scaledx/imb->x; - } - else { - scaledy = (float)layout->prv_h; - scaledx = ( (float)imb->x/(float)imb->y )*layout->prv_h; - scale = scaledy/imb->y; - } - } else { - scaledx = (float)imb->x; - scaledy = (float)imb->y; - scale = 1.0; + uiBut *but; + float fx, fy; + float dx, dy; + int xco, yco; + float scaledx, scaledy; + float scale; + int ex, ey; + + if ( (imb->x > layout->prv_w) || (imb->y > layout->prv_h) ) { + if (imb->x > imb->y) { + scaledx = (float)layout->prv_w; + scaledy = ( (float)imb->y/(float)imb->x )*layout->prv_w; + scale = scaledx/imb->x; } - ex = (int)scaledx; - ey = (int)scaledy; - fx = ((float)layout->prv_w - (float)ex)/2.0f; - fy = ((float)layout->prv_h - (float)ey)/2.0f; - dx = (fx + 0.5f + layout->prv_border_x); - dy = (fy + 0.5f - layout->prv_border_y); - xco = (float)sx + dx; - yco = (float)sy - layout->prv_h + dy; - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* shadow */ - if (dropshadow) - uiDrawBoxShadow(220, xco, yco, xco + ex, yco + ey); - - glEnable(GL_BLEND); - - /* the image */ - glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTexScaled(xco, yco, imb->x, imb->y, GL_UNSIGNED_BYTE, imb->rect, scale, scale); - - /* border */ - if (dropshadow) { - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); - fdrawbox(xco, yco, xco + ex, yco + ey); + else { + scaledy = (float)layout->prv_h; + scaledx = ( (float)imb->x/(float)imb->y )*layout->prv_h; + scale = scaledy/imb->y; } - - glDisable(GL_BLEND); - imb = 0; + } else { + scaledx = (float)imb->x; + scaledy = (float)imb->y; + scale = 1.0; + } + ex = (int)scaledx; + ey = (int)scaledy; + fx = ((float)layout->prv_w - (float)ex)/2.0f; + fy = ((float)layout->prv_h - (float)ey)/2.0f; + dx = (fx + 0.5f + layout->prv_border_x); + dy = (fy + 0.5f - layout->prv_border_y); + xco = (float)sx + dx; + yco = (float)sy - layout->prv_h + dy; + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* shadow */ + if (dropshadow) + uiDrawBoxShadow(220, xco, yco, xco + ex, yco + ey); + + glEnable(GL_BLEND); + + /* the image */ + glColor4f(1.0, 1.0, 1.0, 1.0); + glaDrawPixelsTexScaled(xco, yco, imb->x, imb->y, GL_UNSIGNED_BYTE, imb->rect, scale, scale); + + /* border */ + if (dropshadow) { + glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + fdrawbox(xco, yco, xco + ex, yco + ey); } + + /* dragregion */ + but= uiDefBut(block, LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, ""); + uiButSetDragImage(but, file->path, get_file_icon(file), imb, scale); + + glDisable(GL_BLEND); + imb = 0; + } } static void renamebutton_cb(bContext *C, void *arg1, char *oldname) @@ -491,6 +496,7 @@ void file_draw_list(const bContext *C, ARegion *ar) struct FileList* files = sfile->files; struct direntry *file; ImBuf *imb; + uiBlock *block = uiBeginBlock(C, ar, "FileNames", UI_EMBOSS); int numfiles; int numfiles_layout; int colorid = 0; @@ -526,10 +532,10 @@ void file_draw_list(const bContext *C, ARegion *ar) if (params->active_file == i) { if (file->flags & ACTIVE) colorid= TH_HILITE; else colorid = TH_BACK; - draw_tile(sx-2, sy-3, layout->tile_w+2, sfile->layout->tile_h+layout->tile_border_y, colorid,20); + draw_tile(sx, sy-3, layout->tile_w+4, sfile->layout->tile_h+layout->tile_border_y, colorid,20); } else if (file->flags & ACTIVE) { colorid = TH_HILITE; - draw_tile(sx-2, sy-3, layout->tile_w+2, sfile->layout->tile_h+layout->tile_border_y, colorid,0); + draw_tile(sx, sy-3, layout->tile_w+4, sfile->layout->tile_h+layout->tile_border_y, colorid,0); } } @@ -546,11 +552,11 @@ void file_draw_list(const bContext *C, ARegion *ar) is_icon = 1; } - file_draw_preview(sx, sy, imb, layout, !is_icon && (file->flags & IMAGEFILE)); + file_draw_preview(block, file, sx, sy, imb, layout, !is_icon && (file->flags & IMAGEFILE)); } else { - file_draw_icon(spos, sy-3, get_file_icon(file), ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH); - spos += ICON_DEFAULT_WIDTH + 4; + file_draw_icon(block, file->path, spos, sy-3, get_file_icon(file), ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH); + spos += ICON_DEFAULT_WIDTH + 4; } UI_ThemeColor4(TH_TEXT); @@ -558,15 +564,13 @@ void file_draw_list(const bContext *C, ARegion *ar) sw = file_string_width(file->relname); if (file->flags & EDITING) { int but_width = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : layout->column_widths[COLUMN_NAME]; - uiBlock *block = uiBeginBlock(C, ar, "FileName", UI_EMBOSS); + uiBut *but = uiDefBut(block, TEX, 1, "", spos, sy-layout->tile_h-3, but_width, layout->textheight*2, file->relname, 1.0f, (float)FILE_MAX,0,0,""); uiButSetRenameFunc(but, renamebutton_cb, file); if ( 0 == uiButActiveOnly(C, block, but)) { file->flags &= ~EDITING; } - uiEndBlock(C, block); - uiDrawBlock(C, block); } else { float name_width = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : sw; file_draw_string(spos, sy, file->relname, name_width, layout->tile_h, FILE_SHORTEN_END); @@ -621,6 +625,10 @@ void file_draw_list(const bContext *C, ARegion *ar) if (!sfile->loadimage_timer) sfile->loadimage_timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frames/sec. */ + + uiEndBlock(C, block); + uiDrawBlock(C, block); + } diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 647c1d2be18..93230c79b19 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -588,7 +588,7 @@ int file_exec(bContext *C, wmOperator *exec_op) RNA_string_set(op->ptr, "filename", sfile->params->file); BLI_strncpy(name, sfile->params->dir, sizeof(name)); RNA_string_set(op->ptr, "directory", name); - strcat(name, sfile->params->file); + strcat(name, sfile->params->file); // XXX unsafe if(RNA_struct_find_property(op->ptr, "relative_paths")) if(RNA_boolean_get(op->ptr, "relative_paths")) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 7ccaa6e2789..dbe9417fd2a 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -440,18 +440,36 @@ int folderlist_clear_next(struct SpaceFile *sfile) return 1; } +/* not listbase itself */ void folderlist_free(ListBase* folderlist) { FolderList *folder; if (folderlist){ - for(folder= folderlist->last; folder; folder= folderlist->last) { - MEM_freeN(folder->foldername); - BLI_freelinkN(folderlist, folder); - } + for(folder= folderlist->first; folder; folder= folder->next) + MEM_freeN(folder->foldername); + BLI_freelistN(folderlist); } folderlist= NULL; } +ListBase *folderlist_duplicate(ListBase* folderlist) +{ + + if (folderlist) { + ListBase *folderlistn= MEM_callocN(sizeof(ListBase), "copy folderlist"); + FolderList *folder; + + BLI_duplicatelist(folderlistn, folderlist); + + for(folder= folderlistn->first; folder; folder= folder->next) { + folder->foldername= MEM_dupallocN(folder->foldername); + } + return folderlistn; + } + return NULL; +} + + static void filelist_read_main(struct FileList* filelist); static void filelist_read_library(struct FileList* filelist); static void filelist_read_dir(struct FileList* filelist); @@ -499,6 +517,8 @@ void filelist_free(struct FileList* filelist) filelist->filelist[i].image = 0; if (filelist->filelist[i].relname) MEM_freeN(filelist->filelist[i].relname); + if (filelist->filelist[i].path) + MEM_freeN(filelist->filelist[i].path); filelist->filelist[i].relname = 0; if (filelist->filelist[i].string) MEM_freeN(filelist->filelist[i].string); diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index a8d909f899e..157a2f5cd52 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -81,6 +81,7 @@ void filelist_hideparent(struct FileList* filelist, short hide); struct ListBase * folderlist_new(); void folderlist_free(struct ListBase* folderlist); +struct ListBase * folderlist_duplicate(ListBase* folderlist); void folderlist_popdir(struct ListBase* folderlist, char *dir); void folderlist_pushdir(struct ListBase* folderlist, const char *dir); int folderlist_clear_next(struct SpaceFile* sfile); diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index bf18c938a8a..e73a8c9a7fa 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -173,10 +173,10 @@ static SpaceLink *file_duplicate(SpaceLink *sl) if (sfileo->params) sfilen->files = filelist_new(sfileo->params->type); if(sfileo->folders_prev) - sfilen->folders_prev = MEM_dupallocN(sfileo->folders_prev); + sfilen->folders_prev = folderlist_duplicate(sfileo->folders_prev); if(sfileo->folders_next) - sfilen->folders_next = MEM_dupallocN(sfileo->folders_next); + sfilen->folders_next = folderlist_duplicate(sfileo->folders_next); if(sfileo->params) { sfilen->params= MEM_dupallocN(sfileo->params); @@ -531,7 +531,7 @@ void ED_spacetype_file(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype file region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_HEADER; art->init= file_header_area_init; art->draw= file_header_area_draw; @@ -541,7 +541,7 @@ void ED_spacetype_file(void) /* regions: ui */ art= MEM_callocN(sizeof(ARegionType), "spacetype file region"); art->regionid = RGN_TYPE_UI; - art->minsizey= 60; + art->prefsizey= 60; art->keymapflag= ED_KEYMAP_UI; art->listener= file_ui_area_listener; art->init= file_ui_area_init; @@ -551,7 +551,7 @@ void ED_spacetype_file(void) /* regions: channels (directories) */ art= MEM_callocN(sizeof(ARegionType), "spacetype file region"); art->regionid = RGN_TYPE_CHANNELS; - art->minsizex= 240; + art->prefsizex= 240; art->keymapflag= ED_KEYMAP_UI; art->listener= file_channel_area_listener; art->init= file_channel_area_init; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index bfb2b0f666a..d6342011520 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -616,7 +616,7 @@ void ED_spacetype_ipo(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->listener= graph_region_listener; art->init= graph_header_area_init; @@ -627,7 +627,7 @@ void ED_spacetype_ipo(void) /* regions: channels */ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); art->regionid = RGN_TYPE_CHANNELS; - art->minsizex= 200+V2D_SCROLL_WIDTH; /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */ + art->prefsizex= 200+V2D_SCROLL_WIDTH; /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES; art->listener= graph_region_listener; art->init= graph_channel_area_init; @@ -638,7 +638,7 @@ void ED_spacetype_ipo(void) /* regions: UI buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); art->regionid = RGN_TYPE_UI; - art->minsizex= 200; + art->prefsizex= 200; art->keymapflag= ED_KEYMAP_UI; art->listener= graph_region_listener; art->init= graph_buttons_area_init; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 33b4e37dc8f..ad3407a7414 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -431,10 +431,14 @@ static void image_free(SpaceLink *sl) } -/* spacetype; init callback */ +/* spacetype; init callback, add handlers */ static void image_init(struct wmWindowManager *wm, ScrArea *sa) { + ListBase *lb= WM_dropboxmap_find("Image", SPACE_IMAGE, 0); + /* add drop boxes */ + WM_event_add_dropbox_handler(&sa->handlers, lb); + } static SpaceLink *image_duplicate(SpaceLink *sl) @@ -521,6 +525,31 @@ void image_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "IMAGE_OT_toolbox", SPACEKEY, KM_PRESS, 0, 0); } +/* dropboxes */ +static int image_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +{ + if(drag->type==WM_DRAG_PATH) + if(ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */ + return 1; + return 0; +} + +static void image_drop_copy(wmDrag *drag, wmDropBox *drop) +{ + /* copy drag path to properties */ + RNA_string_set(drop->ptr, "path", drag->path); +} + +/* area+region dropbox definition */ +static void image_dropboxes(void) +{ + ListBase *lb= WM_dropboxmap_find("Image", SPACE_IMAGE, 0); + + WM_dropbox_add(lb, "IMAGE_OT_open", image_drop_poll, image_drop_copy); +} + + + static void image_refresh(const bContext *C, ScrArea *sa) { SpaceImage *sima= CTX_wm_space_image(C); @@ -685,6 +714,7 @@ static void image_main_area_init(wmWindowManager *wm, ARegion *ar) WM_event_add_keymap_handler(&ar->handlers, keymap); keymap= WM_keymap_find(wm->defaultconf, "Image", SPACE_IMAGE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + } static void image_main_area_draw(const bContext *C, ARegion *ar) @@ -825,6 +855,7 @@ void ED_spacetype_image(void) st->duplicate= image_duplicate; st->operatortypes= image_operatortypes; st->keymap= image_keymap; + st->dropboxes= image_dropboxes; st->refresh= image_refresh; st->listener= image_listener; st->context= image_context; @@ -842,7 +873,7 @@ void ED_spacetype_image(void) /* regions: listview/buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype image region"); art->regionid = RGN_TYPE_UI; - art->minsizex= 220; // XXX + art->prefsizex= 220; // XXX art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= image_buttons_area_listener; art->init= image_buttons_area_init; @@ -864,7 +895,7 @@ void ED_spacetype_image(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype image region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->init= image_header_area_init; art->draw= image_header_area_draw; diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index d9662339bb2..af6bec00171 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -204,7 +204,8 @@ void ED_spacetype_info(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype info region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; + art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->listener= info_header_listener; art->init= info_header_area_init; diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index a0ef6c395d4..abe20477914 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -357,7 +357,7 @@ void ED_spacetype_logic(void) /* regions: listview/buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype logic region"); art->regionid = RGN_TYPE_UI; - art->minsizex= 220; // XXX + art->prefsizex= 220; // XXX art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= logic_listener; art->init= logic_buttons_area_init; @@ -369,7 +369,7 @@ void ED_spacetype_logic(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype logic region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->init= logic_header_area_init; art->draw= logic_header_area_draw; diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 77407769f3b..d4f330db303 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -531,7 +531,7 @@ void ED_spacetype_nla(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype nla region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->init= nla_header_area_init; @@ -542,7 +542,7 @@ void ED_spacetype_nla(void) /* regions: channels */ art= MEM_callocN(sizeof(ARegionType), "spacetype nla region"); art->regionid = RGN_TYPE_CHANNELS; - art->minsizex= 200; + art->prefsizex= 200; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D; art->init= nla_channel_area_init; @@ -554,7 +554,7 @@ void ED_spacetype_nla(void) /* regions: UI buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype nla region"); art->regionid = RGN_TYPE_UI; - art->minsizex= 200; + art->prefsizex= 200; art->keymapflag= ED_KEYMAP_UI; art->listener= nla_region_listener; art->init= nla_buttons_area_init; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index dcd07690f0e..2229e19c251 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -376,7 +376,7 @@ void ED_spacetype_node(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype node region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->listener= node_region_listener; art->init= node_header_area_init; @@ -389,7 +389,7 @@ void ED_spacetype_node(void) /* regions: listview/buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype node region"); art->regionid = RGN_TYPE_UI; - art->minsizex= 180; // XXX + art->prefsizex= 180; // XXX art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= node_region_listener; art->init= node_buttons_area_init; diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 84573d44a1d..5048c12c095 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -140,7 +140,7 @@ static void error() {} /* ******************** PROTOTYPES ***************** */ -static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty); +static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty); static void outliner_do_object_operation(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *)); @@ -4087,8 +4087,39 @@ void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot) /* ***************** DRAW *************** */ -static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElement *te) +/* make function calls a bit compacter */ +struct DrawIconArg { + uiBlock *block; + ID *id; + int xmax, x, y; + float alpha; +}; + +static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon) +{ + /* restrict collumn clip... it has been coded by simply overdrawing, doesnt work for buttons */ + if(arg->x >= arg->xmax) + UI_icon_draw(arg->x, arg->y, icon); + else { + uiBut *but= uiDefIconBut(arg->block, LABEL, 0, icon, arg->x-4, arg->y, ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH, NULL, 0.0, 0.0, 1.0, arg->alpha, ""); + if(arg->id) + uiButSetDragID(but, arg->id); + } + +} + +static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, float alpha) { + struct DrawIconArg arg; + + /* make function calls a bit compacter */ + arg.block= block; + arg.id= tselem->id; + arg.xmax= xmax; + arg.x= x; + arg.y= y; + arg.alpha= alpha; + if(tselem->type) { switch( tselem->type) { case TSE_ANIM_DATA: @@ -4219,7 +4250,12 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen UI_icon_draw(x, y, ICON_OBJECT_DATA); break; case TSE_RNA_STRUCT: - UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type)); + if(RNA_struct_is_ID(te->rnaptr.type)) { + arg.id= (ID *)te->rnaptr.data; + tselem_draw_icon_uibut(&arg, RNA_struct_ui_icon(te->rnaptr.type)); + } + else + UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type)); break; default: UI_icon_draw(x, y, ICON_DOT); break; @@ -4228,92 +4264,92 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen else if (GS(tselem->id->name) == ID_OB) { Object *ob= (Object *)tselem->id; switch (ob->type) { - case OB_LAMP: - UI_icon_draw(x, y, ICON_OUTLINER_OB_LAMP); break; + case OB_LAMP: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break; case OB_MESH: - UI_icon_draw(x, y, ICON_OUTLINER_OB_MESH); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break; case OB_CAMERA: - UI_icon_draw(x, y, ICON_OUTLINER_OB_CAMERA); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break; case OB_CURVE: - UI_icon_draw(x, y, ICON_OUTLINER_OB_CURVE); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break; case OB_MBALL: - UI_icon_draw(x, y, ICON_OUTLINER_OB_META); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break; case OB_LATTICE: - UI_icon_draw(x, y, ICON_OUTLINER_OB_LATTICE); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break; case OB_ARMATURE: - UI_icon_draw(x, y, ICON_OUTLINER_OB_ARMATURE); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break; case OB_FONT: - UI_icon_draw(x, y, ICON_OUTLINER_OB_FONT); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break; case OB_SURF: - UI_icon_draw(x, y, ICON_OUTLINER_OB_SURFACE); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break; case OB_EMPTY: - UI_icon_draw(x, y, ICON_OUTLINER_OB_EMPTY); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break; } } else { switch( GS(tselem->id->name)) { case ID_SCE: - UI_icon_draw(x, y, ICON_SCENE_DATA); break; + tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break; case ID_ME: - UI_icon_draw(x, y, ICON_OUTLINER_DATA_MESH); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break; case ID_CU: - UI_icon_draw(x, y, ICON_OUTLINER_DATA_CURVE); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break; case ID_MB: - UI_icon_draw(x, y, ICON_OUTLINER_DATA_META); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break; case ID_LT: - UI_icon_draw(x, y, ICON_OUTLINER_DATA_LATTICE); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break; case ID_LA: { Lamp *la= (Lamp *)tselem->id; switch(la->type) { case LA_LOCAL: - UI_icon_draw(x, y, ICON_LAMP_POINT); break; + tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break; case LA_SUN: - UI_icon_draw(x, y, ICON_LAMP_SUN); break; + tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break; case LA_SPOT: - UI_icon_draw(x, y, ICON_LAMP_SPOT); break; + tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break; case LA_HEMI: - UI_icon_draw(x, y, ICON_LAMP_HEMI); break; + tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break; case LA_AREA: - UI_icon_draw(x, y, ICON_LAMP_AREA); break; + tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break; default: - UI_icon_draw(x, y, ICON_OUTLINER_DATA_LAMP); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break; } break; } case ID_MA: - UI_icon_draw(x, y, ICON_MATERIAL_DATA); break; + tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break; case ID_TE: - UI_icon_draw(x, y, ICON_TEXTURE_DATA); break; + tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break; case ID_IM: - UI_icon_draw(x, y, ICON_IMAGE_DATA); break; + tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break; case ID_SO: - UI_icon_draw(x, y, ICON_SPEAKER); break; + tselem_draw_icon_uibut(&arg, ICON_SPEAKER); break; case ID_AR: - UI_icon_draw(x, y, ICON_OUTLINER_DATA_ARMATURE); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break; case ID_CA: - UI_icon_draw(x, y, ICON_OUTLINER_DATA_CAMERA); break; + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break; case ID_KE: - UI_icon_draw(x, y, ICON_SHAPEKEY_DATA); break; + tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break; case ID_WO: - UI_icon_draw(x, y, ICON_WORLD_DATA); break; + tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break; case ID_AC: - UI_icon_draw(x, y, ICON_ACTION); break; + tselem_draw_icon_uibut(&arg, ICON_ACTION); break; case ID_NLA: - UI_icon_draw(x, y, ICON_NLA); break; + tselem_draw_icon_uibut(&arg, ICON_NLA); break; case ID_TXT: - UI_icon_draw(x, y, ICON_SCRIPT); break; + tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break; case ID_GR: - UI_icon_draw(x, y, ICON_GROUP); break; + tselem_draw_icon_uibut(&arg, ICON_GROUP); break; case ID_LI: - UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT); break; + tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break; } } } -static void outliner_draw_iconrow(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, int level, int *offsx, int ys) +static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys) { TreeElement *te; TreeStoreElem *tselem; @@ -4338,10 +4374,10 @@ static void outliner_draw_iconrow(bContext *C, Scene *scene, SpaceOops *soops, L uiSetRoundBox(15); glColor4ub(255, 255, 255, 100); uiRoundBox( (float)*offsx-0.5f, (float)ys-1.0f, (float)*offsx+OL_H-3.0f, (float)ys+OL_H-3.0f, OL_H/2.0f-2.0f); - glEnable(GL_BLEND); + glEnable(GL_BLEND); /* roundbox disables */ } - tselem_draw_icon((float)*offsx, (float)ys, tselem, te); + tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f); te->xs= (float)*offsx; te->ys= (float)ys; te->xend= (short)*offsx+OL_X; @@ -4352,12 +4388,12 @@ static void outliner_draw_iconrow(bContext *C, Scene *scene, SpaceOops *soops, L /* this tree element always has same amount of branches, so dont draw */ if(tselem->type!=TSE_R_LAYER) - outliner_draw_iconrow(C, scene, soops, &te->subtree, level+1, offsx, ys); + outliner_draw_iconrow(C, block, scene, soops, &te->subtree, level+1, xmax, offsx, ys); } } -static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty) +static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty) { TreeElement *ten; TreeStoreElem *tselem; @@ -4366,7 +4402,12 @@ static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, S tselem= TREESTORE(te); if(*starty+2*OL_H >= ar->v2d.cur.ymin && *starty<= ar->v2d.cur.ymax) { - + int xmax= ar->v2d.cur.xmax; + + /* icons can be ui buts, we dont want it to overlap with restrict */ + if((soops->flag & SO_HIDE_RESTRICTCOLS)==0) + xmax-= OL_TOGW+ICON_DEFAULT_WIDTH; + glEnable(GL_BLEND); /* colors for active/selected data */ @@ -4439,8 +4480,9 @@ static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, S /* datatype icon */ if(!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) { - // icons a bit higher - tselem_draw_icon((float)startx+offsx, (float)*starty+2, tselem, te); + // icons a bit higher + tselem_draw_icon(block, xmax, (float)startx+offsx, (float)*starty+2, tselem, te, 1.0f); + offsx+= OL_X; } else @@ -4472,6 +4514,7 @@ static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, S if(tselem->type==0 && te->idcode==ID_SCE); else if(tselem->type!=TSE_R_LAYER) { /* this tree element always has same amount of branches, so dont draw */ int tempx= startx+offsx; + // divider UI_ThemeColorShade(TH_BACK, -40); glRecti(tempx -10, *starty+4, tempx -8, *starty+OL_H-4); @@ -4479,8 +4522,8 @@ static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, S glEnable(GL_BLEND); glPixelTransferf(GL_ALPHA_SCALE, 0.5); - outliner_draw_iconrow(C, scene, soops, &te->subtree, 0, &tempx, *starty+2); - + outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty+2); + glPixelTransferf(GL_ALPHA_SCALE, 1.0); glDisable(GL_BLEND); } @@ -4496,7 +4539,7 @@ static void outliner_draw_tree_element(bContext *C, Scene *scene, ARegion *ar, S if((tselem->flag & TSE_CLOSED)==0) { for(ten= te->subtree.first; ten; ten= ten->next) { - outliner_draw_tree_element(C, scene, ar, soops, ten, startx+OL_X, starty); + outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx+OL_X, starty); } } } @@ -4575,7 +4618,7 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, } -static void outliner_draw_tree(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops) +static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops) { TreeElement *te; int starty, startx; @@ -4607,7 +4650,7 @@ static void outliner_draw_tree(bContext *C, Scene *scene, ARegion *ar, SpaceOops starty= (int)ar->v2d.tot.ymax-OL_H; startx= 0; for(te= soops->tree.first; te; te= te->next) { - outliner_draw_tree_element(C, scene, ar, soops, te, startx, &starty); + outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty); } } @@ -5355,10 +5398,10 @@ void draw_outliner(const bContext *C) /* draw outliner stuff (background and hierachy lines) */ outliner_back(ar, soops); - outliner_draw_tree((bContext *)C, scene, ar, soops); + block= uiBeginBlock(C, ar, "outliner buttons", UI_EMBOSS); + outliner_draw_tree((bContext *)C, block, scene, ar, soops); /* draw icons and names */ - block= uiBeginBlock(C, ar, "outliner buttons", UI_EMBOSS); outliner_buttons(C, block, ar, soops, &soops->tree); if(ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) { diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 568c0b353e3..c62f2fee66a 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -286,7 +286,7 @@ void ED_spacetype_outliner(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype time region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->init= outliner_header_area_init; diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index b882a3313cd..89f5eefae88 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -219,7 +219,7 @@ void ED_spacetype_script(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype script region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_HEADER; art->init= script_header_area_init; diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 354b4712ce4..29995c89662 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -433,7 +433,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent *event) { - sequencer_generic_invoke_xy__internal(C, op, event, 0); + sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME); return WM_operator_filesel(C, op, event); //return sequencer_add_image_strip_exec(C, op); } @@ -457,7 +457,7 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE, FILE_SPECIAL); - sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILES); + sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_ENDFRAME|SEQPROP_FILES); } diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 25364aed5ca..d2b13ac7912 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -237,7 +237,7 @@ static void sequencer_free(SpaceLink *sl) /* spacetype; init callback */ static void sequencer_init(struct wmWindowManager *wm, ScrArea *sa) { - + } static SpaceLink *sequencer_duplicate(SpaceLink *sl) @@ -251,11 +251,13 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) } + /* *********************** sequencer (main) region ************************ */ /* add handlers, stuff you only do once or on area/region changes */ static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar) { wmKeyMap *keymap; + ListBase *lb; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); @@ -265,6 +267,12 @@ static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar) /* own keymap */ keymap= WM_keymap_find(wm->defaultconf, "Sequencer", SPACE_SEQ, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + + /* add drop boxes */ + lb= WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW); + + WM_event_add_dropbox_handler(&ar->handlers, lb); + } static void sequencer_main_area_draw(const bContext *C, ARegion *ar) @@ -275,6 +283,40 @@ static void sequencer_main_area_draw(const bContext *C, ARegion *ar) draw_timeline_seq(C, ar); } +/* ************* dropboxes ************* */ + +static int image_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +{ + if(drag->type==WM_DRAG_PATH) + if(ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */ + return 1; + return 0; +} + +static int movie_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +{ + if(drag->type==WM_DRAG_PATH) + if(ELEM(drag->icon, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */ + return 1; + return 0; +} + +static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop) +{ + /* copy drag path to properties */ + RNA_string_set(drop->ptr, "path", drag->path); +} + +/* this region dropbox definition */ +static void sequencer_dropboxes(void) +{ + ListBase *lb= WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW); + + WM_dropbox_add(lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy); + WM_dropbox_add(lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy); +} + +/* ************* end drop *********** */ /* add handlers, stuff you only do once or on area/region changes */ static void sequencer_header_area_init(wmWindowManager *wm, ARegion *ar) @@ -421,7 +463,8 @@ void ED_spacetype_sequencer(void) st->duplicate= sequencer_duplicate; st->operatortypes= sequencer_operatortypes; st->keymap= sequencer_keymap; - + st->dropboxes= sequencer_dropboxes; + /* regions: main window */ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region"); art->regionid = RGN_TYPE_WINDOW; @@ -435,7 +478,7 @@ void ED_spacetype_sequencer(void) /* preview */ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region"); art->regionid = RGN_TYPE_PREVIEW; - art->minsizey = 240; // XXX + art->prefsizey = 240; // XXX art->init= sequencer_preview_area_init; art->draw= sequencer_preview_area_draw; art->listener= sequencer_preview_area_listener; @@ -445,7 +488,7 @@ void ED_spacetype_sequencer(void) /* regions: listview/buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region"); art->regionid = RGN_TYPE_UI; - art->minsizex= 220; // XXX + art->prefsizex= 220; // XXX art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= sequencer_buttons_area_listener; art->init= sequencer_buttons_area_init; @@ -459,7 +502,7 @@ void ED_spacetype_sequencer(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->init= sequencer_header_area_init; diff --git a/source/blender/editors/space_sound/space_sound.c b/source/blender/editors/space_sound/space_sound.c index 1cd5ab65c0f..f77afb6e168 100644 --- a/source/blender/editors/space_sound/space_sound.c +++ b/source/blender/editors/space_sound/space_sound.c @@ -246,7 +246,7 @@ void ED_spacetype_sound(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype sound region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_HEADER; art->init= sound_header_area_init; @@ -257,7 +257,7 @@ void ED_spacetype_sound(void) /* regions: channels */ art= MEM_callocN(sizeof(ARegionType), "spacetype sound region"); art->regionid = RGN_TYPE_CHANNELS; - art->minsizex= 80; + art->prefsizex= 80; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D; // art->init= sound_channel_area_init; diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index be90834a371..77e0efafd0b 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -433,7 +433,7 @@ void ED_spacetype_text(void) /* regions: properties */ art= MEM_callocN(sizeof(ARegionType), "spacetype text region"); art->regionid = RGN_TYPE_UI; - art->minsizex= UI_COMPACT_PANEL_WIDTH; + art->prefsizex= UI_COMPACT_PANEL_WIDTH; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D; art->init= text_properties_area_init; @@ -443,7 +443,7 @@ void ED_spacetype_text(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype text region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_HEADER; art->init= text_header_area_init; diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 4f9f4975629..7b935ae916b 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -432,7 +432,7 @@ void ED_spacetype_time(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype time region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->init= time_header_area_init; diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index f45e08be697..7b522482db1 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -175,7 +175,7 @@ void ED_spacetype_userpref(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype userpref region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_HEADER; art->listener= userpref_header_listener; art->init= userpref_header_area_init; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index b3bd31d53ac..da64c10b277 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -319,6 +319,7 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar) { + ListBase *lb; wmKeyMap *keymap; /* object ops. */ @@ -386,8 +387,62 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar) keymap= WM_keymap_find(wm->defaultconf, "3D View", SPACE_VIEW3D, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); + + /* add drop boxes */ + lb= WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW); + + WM_event_add_dropbox_handler(&ar->handlers, lb); + +} + +static int view3d_ob_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +{ + if(drag->type==WM_DRAG_ID) { + ID *id= (ID *)drag->poin; + if( GS(id->name)==ID_OB ) + return 1; + } + return 0; +} + +static int view3d_mat_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +{ + if(drag->type==WM_DRAG_ID) { + ID *id= (ID *)drag->poin; + if( GS(id->name)==ID_MA ) + return 1; + } + return 0; +} + +static int view3d_ima_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +{ + if(drag->type==WM_DRAG_ID) { + ID *id= (ID *)drag->poin; + if( GS(id->name)==ID_IM ) + return 1; + } + return 0; +} + +static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop) +{ + ID *id= (ID *)drag->poin; + RNA_string_set(drop->ptr, "name", id->name+2); } +/* region dropbox definition */ +static void view3d_dropboxes(void) +{ + ListBase *lb= WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW); + + WM_dropbox_add(lb, "OBJECT_OT_add_named_cursor", view3d_ob_drop_poll, view3d_id_drop_copy); + WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy); + WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_drop_poll, view3d_id_drop_copy); +} + + + /* type callback, not region itself */ static void view3d_main_area_free(ARegion *ar) { @@ -822,6 +877,7 @@ void ED_spacetype_view3d(void) st->duplicate= view3d_duplicate; st->operatortypes= view3d_operatortypes; st->keymap= view3d_keymap; + st->dropboxes= view3d_dropboxes; st->context= view3d_context; /* regions: main window */ @@ -839,7 +895,7 @@ void ED_spacetype_view3d(void) /* regions: listview/buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region"); art->regionid = RGN_TYPE_UI; - art->minsizex= 180; // XXX + art->prefsizex= 180; // XXX art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= view3d_buttons_area_listener; art->init= view3d_buttons_area_init; @@ -851,8 +907,8 @@ void ED_spacetype_view3d(void) /* regions: tool(bar) */ art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region"); art->regionid = RGN_TYPE_TOOLS; - art->minsizex= 160; // XXX - art->minsizey= 50; // XXX + art->prefsizex= 160; // XXX + art->prefsizey= 50; // XXX art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= view3d_buttons_area_listener; art->init= view3d_tools_area_init; @@ -864,8 +920,8 @@ void ED_spacetype_view3d(void) /* regions: tool properties */ art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region"); art->regionid = RGN_TYPE_TOOL_PROPS; - art->minsizex= 0; - art->minsizey= 120; + art->prefsizex= 0; + art->prefsizey= 120; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= view3d_buttons_area_listener; art->init= view3d_tools_area_init; @@ -878,7 +934,7 @@ void ED_spacetype_view3d(void) /* regions: header */ art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region"); art->regionid = RGN_TYPE_HEADER; - art->minsizey= HEADERY; + art->prefsizey= HEADERY; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; art->listener= view3d_header_area_listener; art->init= view3d_header_area_init; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index f7f053b2195..6cad57f03d5 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1006,6 +1006,123 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff return 0; } +/* returns basact */ +static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, short *mval, Base *startbase, int has_bones) +{ + Scene *scene= vc->scene; + View3D *v3d= vc->v3d; + Base *base, *basact= NULL; + static short lastmval[2]={-100, -100}; + int a, donearest= 0; + + /* define if we use solid nearest select or not */ + if(v3d->drawtype>OB_WIRE) { + donearest= 1; + if( ABS(mval[0]-lastmval[0])<3 && ABS(mval[1]-lastmval[1])<3) { + if(!has_bones) /* hrms, if theres bones we always do nearest */ + donearest= 0; + } + } + lastmval[0]= mval[0]; lastmval[1]= mval[1]; + + if(donearest) { + unsigned int min= 0xFFFFFFFF; + int selcol= 0, notcol=0; + + + if(has_bones) { + /* we skip non-bone hits */ + for(a=0; a<hits; a++) { + if( min > buffer[4*a+1] && (buffer[4*a+3] & 0xFFFF0000) ) { + min= buffer[4*a+1]; + selcol= buffer[4*a+3] & 0xFFFF; + } + } + } + else { + /* only exclude active object when it is selected... */ + if(BASACT && (BASACT->flag & SELECT) && hits>1) notcol= BASACT->selcol; + + for(a=0; a<hits; a++) { + if( min > buffer[4*a+1] && notcol!=(buffer[4*a+3] & 0xFFFF)) { + min= buffer[4*a+1]; + selcol= buffer[4*a+3] & 0xFFFF; + } + } + } + + base= FIRSTBASE; + while(base) { + if(base->lay & v3d->lay) { + if(base->selcol==selcol) break; + } + base= base->next; + } + if(base) basact= base; + } + else { + + base= startbase; + while(base) { + /* skip objects with select restriction, to prevent prematurely ending this loop + * with an un-selectable choice */ + if (base->object->restrictflag & OB_RESTRICT_SELECT) { + base=base->next; + if(base==NULL) base= FIRSTBASE; + if(base==startbase) break; + } + + if(base->lay & v3d->lay) { + for(a=0; a<hits; a++) { + if(has_bones) { + /* skip non-bone objects */ + if((buffer[4*a+3] & 0xFFFF0000)) { + if(base->selcol== (buffer[(4*a)+3] & 0xFFFF)) + basact= base; + } + } + else { + if(base->selcol== (buffer[(4*a)+3] & 0xFFFF)) + basact= base; + } + } + } + + if(basact) break; + + base= base->next; + if(base==NULL) base= FIRSTBASE; + if(base==startbase) break; + } + } + + return basact; +} + +/* mval comes from event->mval, only use within region handlers */ +Base *ED_view3d_give_base_under_cursor(bContext *C, short *mval) +{ + ViewContext vc; + Base *basact= NULL; + unsigned int buffer[4*MAXPICKBUF]; + int hits; + + /* setup view context for argument to callbacks */ + view3d_operator_needs_opengl(C); + view3d_set_viewcontext(C, &vc); + + hits= mixed_bones_object_selectbuffer(&vc, buffer, mval); + + if(hits>0) { + int a, has_bones= 0; + + for(a=0; a<hits; a++) if(buffer[4*a+3] & 0xFFFF0000) has_bones= 1; + + basact= mouse_select_eval_buffer(&vc, buffer, hits, mval, vc.scene->base.first, has_bones); + } + + return basact; +} /* mval is region coords */ static int mouse_select(bContext *C, short *mval, short extend, short obcenter, short enumerate) @@ -1070,89 +1187,7 @@ static int mouse_select(bContext *C, short *mval, short extend, short obcenter, if(has_bones==0 && enumerate) { basact= mouse_select_menu(C, &vc, buffer, hits, mval, extend); } else { - static short lastmval[2]={-100, -100}; - int donearest= 0; - - /* define if we use solid nearest select or not */ - if(v3d->drawtype>OB_WIRE) { - donearest= 1; - if( ABS(mval[0]-lastmval[0])<3 && ABS(mval[1]-lastmval[1])<3) { - if(!has_bones) /* hrms, if theres bones we always do nearest */ - donearest= 0; - } - } - lastmval[0]= mval[0]; lastmval[1]= mval[1]; - - if(donearest) { - unsigned int min= 0xFFFFFFFF; - int selcol= 0, notcol=0; - - - if(has_bones) { - /* we skip non-bone hits */ - for(a=0; a<hits; a++) { - if( min > buffer[4*a+1] && (buffer[4*a+3] & 0xFFFF0000) ) { - min= buffer[4*a+1]; - selcol= buffer[4*a+3] & 0xFFFF; - } - } - } - else { - /* only exclude active object when it is selected... */ - if(BASACT && (BASACT->flag & SELECT) && hits>1) notcol= BASACT->selcol; - - for(a=0; a<hits; a++) { - if( min > buffer[4*a+1] && notcol!=(buffer[4*a+3] & 0xFFFF)) { - min= buffer[4*a+1]; - selcol= buffer[4*a+3] & 0xFFFF; - } - } - } - - base= FIRSTBASE; - while(base) { - if(base->lay & v3d->lay) { - if(base->selcol==selcol) break; - } - base= base->next; - } - if(base) basact= base; - } - else { - - base= startbase; - while(base) { - /* skip objects with select restriction, to prevent prematurely ending this loop - * with an un-selectable choice */ - if (base->object->restrictflag & OB_RESTRICT_SELECT) { - base=base->next; - if(base==NULL) base= FIRSTBASE; - if(base==startbase) break; - } - - if(base->lay & v3d->lay) { - for(a=0; a<hits; a++) { - if(has_bones) { - /* skip non-bone objects */ - if((buffer[4*a+3] & 0xFFFF0000)) { - if(base->selcol== (buffer[(4*a)+3] & 0xFFFF)) - basact= base; - } - } - else { - if(base->selcol== (buffer[(4*a)+3] & 0xFFFF)) - basact= base; - } - } - } - - if(basact) break; - - base= base->next; - if(base==NULL) base= FIRSTBASE; - if(base==startbase) break; - } - } + basact= mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, has_bones); } if(has_bones && basact) { diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 12f61cbb026..8a0c02d729e 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -60,8 +60,8 @@ typedef struct bScreen { short do_refresh; /* notifier for scale screen, changed screen, etc */ short do_draw_gesture; /* notifier for gesture draw. */ short do_draw_paintcursor; /* notifier for paint cursor draw. */ + short do_draw_drag; /* notifier for dragging draw. */ short swap; /* indicator to survive swap-exchange systems */ - short pad; short mainwin; /* screensize subwindow, for screenedges and global menus */ short subwinactive; /* active subwindow */ @@ -148,11 +148,11 @@ typedef struct ARegion { short alignment; /* how it should split */ short flag; /* hide, ... */ - float fsize; /* current split size in float */ + float fsize; /* current split size in float (unused) */ + short sizex, sizey; /* current split size in pixels (if zero it uses regiontype) */ short do_draw; /* private, cached notifier events */ short swap; /* private, indicator to survive swap-exchange */ - int pad1; struct ARegionType *type; /* callbacks for this region type */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 7df49bfb2e2..8e1042f3e12 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -121,6 +121,8 @@ typedef struct wmWindowManager { ListBase paintcursors; /* extra overlay cursors to draw, like circles */ + ListBase drags; /* active dragged items */ + ListBase keyconfigs; /* known key configurations */ struct wmKeyConfig *defaultconf; /* default configuration, not saved */ @@ -290,6 +292,8 @@ typedef struct wmOperator { #define OPERATOR_FINISHED 4 /* add this flag if the event should pass through */ #define OPERATOR_PASS_THROUGH 8 +/* in case operator got executed outside WM code... like via fileselect */ +#define OPERATOR_HANDLED 16 /* wmOperator flag */ #define OP_GRAB_POINTER 1 diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index b4cedf82a50..e4ae6ad4f5b 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -44,6 +44,9 @@ struct rcti; struct PointerRNA; struct EnumPropertyItem; struct MenuType; +struct wmDropBox; +struct wmDrag; +struct ImBuf; typedef struct wmJob wmJob; @@ -155,9 +158,13 @@ void WM_event_remove_area_handler(struct ListBase *handlers, void *area); struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op); void WM_event_remove_handlers(struct bContext *C, ListBase *handlers); +struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase *dropboxes); + + /* mouse */ void WM_event_add_mousemove(struct bContext *C); int WM_modal_tweak_exit(struct wmEvent *evt, int tweak_event); + /* notifiers */ void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference); void WM_main_add_notifier(unsigned int type, void *reference); @@ -248,6 +255,7 @@ void WM_OT_tweak_gesture(struct wmOperatorType *ot); /* Gesture manager API */ struct wmGesture *WM_gesture_new(struct bContext *C, struct wmEvent *event, int type); void WM_gesture_end(struct bContext *C, struct wmGesture *gesture); +void WM_gestures_remove(struct bContext *C); /* radial control operator */ int WM_radial_control_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); @@ -259,6 +267,14 @@ void WM_radial_control_string(struct wmOperator *op, char str[], int maxlen); void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op); void WM_event_fileselect_event(struct bContext *C, void *ophandle, int eventval); + /* drag and drop */ +struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value); +void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx, int sy); + +struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(struct bContext *, struct wmDrag *, struct wmEvent *event), + void (*copy)(struct wmDrag *, struct wmDropBox *)); +ListBase *WM_dropboxmap_find(char *idname, int spaceid, int regionid); + /* OpenGL wrappers, mimicking opengl syntax */ void wmSubWindowSet (struct wmWindow *win, int swinid); void wmSubWindowScissorSet (struct wmWindow *win, int swinid, struct rcti *srct); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 4caa4b973f1..0439fa8b8f5 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -33,9 +33,11 @@ struct wmEvent; struct wmWindowManager; struct uiLayout; struct wmOperator; +struct ImBuf; #include "RNA_types.h" #include "DNA_listBase.h" +#include "BKE_utildefines.h" /* FILE_MAX */ /* exported types for WM */ #include "wm_cursors.h" @@ -437,7 +439,51 @@ typedef struct wmReport { char *message; } wmReport; -/* *************** migrated stuff, clean later? ******************************** */ +/* *************** Drag and drop *************** */ + +#define WM_DRAG_ID 0 +#define WM_DRAG_RNA 1 +#define WM_DRAG_PATH 2 +#define WM_DRAG_NAME 3 +#define WM_DRAG_VALUE 4 + +/* note: structs need not exported? */ + +typedef struct wmDrag { + struct wmDrag *next, *prev; + + int icon, type; /* type, see WM_DRAG defines above */ + void *poin; + char path[FILE_MAX]; + double value; + + struct ImBuf *imb; /* if no icon but imbuf should be drawn around cursor */ + float scale; + short sx, sy; + + char opname[FILE_MAX]; /* if set, draws operator name*/ +} wmDrag; + +/* dropboxes are like keymaps, part of the screen/area/region definition */ +/* allocation and free is on startup and exit */ +typedef struct wmDropBox { + struct wmDropBox *next, *prev; + + /* test if the dropbox is active, then can print optype name */ + int (*poll)(struct bContext *, struct wmDrag *, wmEvent *); + + /* before exec, this copies drag info to wmDrop properties */ + void (*copy)(struct wmDrag *, struct wmDropBox *); + + /* if poll survives, operator is called */ + wmOperatorType *ot; /* not saved in file, so can be pointer */ + + struct IDProperty *properties; /* operator properties, assigned to ptr->data and can be written to a file */ + struct PointerRNA *ptr; /* rna pointer to access properties */ + +} wmDropBox; + +/* *************** migrated stuff, clean later? ************** */ typedef struct RecentFile { struct RecentFile *next, *prev; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index ee1d76020c2..7f4bb59bbae 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -298,6 +298,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) BLI_freelistN(&wm->queue); BLI_freelistN(&wm->paintcursors); + BLI_freelistN(&wm->drags); BKE_reports_clear(&wm->reports); if(C && CTX_wm_manager(C)==wm) CTX_wm_manager_set(C, NULL); diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index dfcc1fcd227..f23688404b1 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -64,6 +64,7 @@ static GHOST_TStandardCursor convert_cursor(int curs) 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; } } @@ -136,9 +137,10 @@ void WM_cursor_set(wmWindow *win, int curs) void WM_cursor_modal(wmWindow *win, int val) { - if(win->lastcursor == 0) + if(win->lastcursor == 0) { win->lastcursor = win->cursor; - WM_cursor_set(win, val); + WM_cursor_set(win, val); + } } void WM_cursor_restore(wmWindow *win) diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c new file mode 100644 index 00000000000..d976c42bb8c --- /dev/null +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -0,0 +1,370 @@ +/** + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "string.h" + +#include "DNA_windowmanager_types.h" +#include "DNA_screen_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_idprop.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_screen.h" +#include "BKE_global.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "UI_interface.h" +#include "UI_interface_icons.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "wm_event_system.h" +#include "wm.h" + +#include "RNA_types.h" + +/* ****************************************************** */ + +static ListBase dropboxes= {NULL, NULL}; + +/* drop box maps are stored global for now */ +/* these are part of blender's UI/space specs, and not like keymaps */ +/* when editors become configurable, they can add own dropbox definitions */ + +typedef struct wmDropBoxMap { + struct wmDropBoxMap *next, *prev; + + ListBase dropboxes; + short spaceid, regionid; + char idname[KMAP_MAX_NAME]; + +} wmDropBoxMap; + +ListBase *WM_dropboxmap_find(char *idname, int spaceid, int regionid) +{ + wmDropBoxMap *dm; + + for(dm= dropboxes.first; dm; dm= dm->next) + if(dm->spaceid==spaceid && dm->regionid==regionid) + if(0==strncmp(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, int (*poll)(bContext *, wmDrag *, wmEvent *), + void (*copy)(wmDrag *, wmDropBox *)) +{ + wmDropBox *drop= MEM_callocN(sizeof(wmDropBox), "wmDropBox"); + + drop->poll= poll; + drop->copy= copy; + drop->ot= WM_operatortype_find(idname, 0); + + 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); + + return drop; +} + +void wm_dropbox_free(void) +{ + wmDropBoxMap *dm; + + 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); + } + + 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) +{ + 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->icon= icon; + drag->type= type; + if(type==WM_DRAG_PATH) + BLI_strncpy(drag->path, poin, FILE_MAX); + 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; +} + + +static char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, wmEvent *event) +{ + wmEventHandler *handler= handlers->first; + for(; handler; handler= handler->next) { + if(handler->dropboxes) { + wmDropBox *drop= handler->dropboxes->first; + for(; drop; drop= drop->next) { + if(drop->poll(C, drag, event)) + return drop->ot->name; + } + } + } + return NULL; +} + +/* return active operator name when mouse is in box */ +static char *wm_dropbox_active(bContext *C, wmDrag *drag, wmEvent *event) +{ + wmWindow *win= CTX_wm_window(C); + ScrArea *sa= CTX_wm_area(C); + ARegion *ar= CTX_wm_region(C); + 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, wmEvent *event) +{ + wmWindow *win= CTX_wm_window(C); + + /* for multiwin drags, we only do this if mouse inside */ + if(event->x<0 || event->y<0 || event->x>win->sizex || event->y>win->sizey) + return; + + drag->opname[0]= 0; + + /* check buttons (XXX todo rna and value) */ + if( UI_but_active_drop_name(C) ) { + strcpy(drag->opname, "Paste name"); + } + else { + char *opname= wm_dropbox_active(C, drag, event); + + if(opname) { + BLI_strncpy(drag->opname, opname, FILE_MAX); + // WM_cursor_modal(win, CURSOR_COPY); + } + // else + // WM_cursor_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, wmEvent *event) +{ + wmWindowManager *wm= CTX_wm_manager(C); + wmDrag *drag; + + for(drag= wm->drags.first; drag; drag= drag->next) { + wm_drop_operator_options(C, drag, event); + } +} + +/* ************** draw ***************** */ + +static void wm_drop_operator_draw(char *name, int x, int y) +{ + int width= UI_GetStringWidth(name); + + glColor4ub(0, 0, 0, 128); + + uiSetRoundBox(15); + uiRoundBox(x, y, x + width + 8, y + 15, 7); + + glColor4ub(255, 255, 255, 255); + UI_DrawString(x+4, y+4, name); +} + +static char *wm_drag_name(wmDrag *drag) +{ + switch(drag->type) { + case WM_DRAG_ID: + { + ID *id= (ID *)drag->poin; + return id->name+2; + } + case WM_DRAG_PATH: + return drag->path; + case WM_DRAG_NAME: + return (char *)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; +} + +/* called in wm_draw.c */ +/* if rect set, do not draw */ +void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) +{ + wmWindowManager *wm= CTX_wm_manager(C); + wmDrag *drag; + 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 */ + glEnable(GL_BLEND); + for(drag= wm->drags.first; drag; drag= drag->next) { + + /* 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 { + glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */ + glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, drag->imb->rect, drag->scale, drag->scale); + } + } + else { + x= cursorx - 8; + y= cursory - 2; + + /* icons assumed to be 16 pixels */ + if(rect) + drag_rect_minmax(rect, x, y, x+16, y+16); + else + UI_icon_draw_aspect(x, y, drag->icon, 1.0, 0.8); + } + + /* item name */ + if(drag->imb) { + x= cursorx - drag->sx/2; + y= cursory - drag->sy/2 - 16; + } + else { + x= cursorx + 10; + y= cursory + 1; + } + + if(rect) { + int w= UI_GetStringWidth(wm_drag_name(drag)); + drag_rect_minmax(rect, x, y, x+w, y+16); + } + else { + glColor4ub(255, 255, 255, 255); + UI_DrawString(x, y, wm_drag_name(drag)); + } + + /* operator name with roundbox */ + if(drag->opname[0]) { + if(drag->imb) { + x= cursorx - drag->sx/2; + y= cursory + drag->sy/2 + 4; + } + else { + x= cursorx - 8; + y= cursory + 16; + } + + if(rect) { + int w= UI_GetStringWidth(wm_drag_name(drag)); + drag_rect_minmax(rect, x, y, x+w, y+16); + } + else + wm_drop_operator_draw(drag->opname, x, y); + + } + } + glDisable(GL_BLEND); +} diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 9ee67cd4047..0d2f1043d0b 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -63,7 +63,8 @@ #define WIN_FRONT_OK 2 #define WIN_BOTH_OK 3 -/* ********************* drawing, swap ****************** */ +/* ******************* drawing, overlays *************** */ + static void wm_paintcursor_draw(bContext *C, ARegion *ar) { @@ -91,6 +92,8 @@ static void wm_paintcursor_draw(bContext *C, ARegion *ar) } } +/* ********************* drawing, swap ****************** */ + static void wm_area_mark_invalid_backbuf(ScrArea *sa) { if(sa->spacetype == SPACE_VIEW3D) @@ -179,9 +182,11 @@ static void wm_flush_regions_up(bScreen *screen, rcti *dirty) static void wm_method_draw_overlap_all(bContext *C, wmWindow *win) { + wmWindowManager *wm= CTX_wm_manager(C); bScreen *screen= win->screen; ScrArea *sa; ARegion *ar; + static rcti rect= {0, 0, 0, 0}; int exchange= (G.f & G_SWAP_EXCHANGE); /* flush overlapping regions */ @@ -203,6 +208,16 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win) wm_flush_regions_down(screen, &ar->winrct); } + /* flush drag item */ + if(rect.xmin!=rect.xmax) { + wm_flush_regions_down(screen, &rect); + rect.xmin= rect.xmax = 0; + } + if(wm->drags.first) { + /* doesnt draw, fills rect with boundbox */ + wm_drags_draw(C, win, &rect); + } + /* draw marked area regions */ for(sa= screen->areabase.first; sa; sa= sa->next) { CTX_wm_area_set(C, sa); @@ -273,6 +288,11 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win) if(screen->do_draw_gesture) wm_gesture_draw(win); + + /* needs pixel coords in screen */ + if(wm->drags.first) { + wm_drags_draw(C, win, NULL); + } } #if 0 @@ -607,6 +627,12 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) wmSubWindowSet(win, screen->mainwin); } + + /* needs pixel coords in screen */ + if(wm->drags.first) { + wm_drags_draw(C, win, NULL); + } + } /****************** main update call **********************/ @@ -625,6 +651,8 @@ static int wm_draw_update_test_window(wmWindow *win) return 1; if(win->screen->do_draw_paintcursor) return 1; + if(win->screen->do_draw_drag) + return 1; for(ar= win->screen->regionbase.first; ar; ar= ar->next) if(ar->swinid && ar->do_draw) @@ -672,6 +700,7 @@ void wm_draw_update(bContext *C) win->screen->do_draw_gesture= 0; win->screen->do_draw_paintcursor= 0; + win->screen->do_draw_drag= 0; wm_window_swap_buffers(win); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 7fa5f9b61c0..8ba8ed1824d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -81,8 +81,15 @@ void wm_event_add(wmWindow *win, wmEvent *event_to_add) void wm_event_free(wmEvent *event) { - if(event->customdata && event->customdatafree) - MEM_freeN(event->customdata); + if(event->customdata) { + if(event->customdatafree) { + /* note: pointer to listbase struct elsewhere */ + if(event->custom==EVT_DATA_LISTBASE) + BLI_freelistN(event->customdata); + else + MEM_freeN(event->customdata); + } + } MEM_freeN(event); } @@ -336,7 +343,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat) else if(repeat==0) WM_operator_free(op); - return retval; + return retval | OPERATOR_HANDLED; } @@ -483,7 +490,9 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P wm_operator_print(op); } - if(retval & OPERATOR_FINISHED) { + if(retval & OPERATOR_HANDLED) + ; /* do nothing, wm_operator_exec() has been called somewhere */ + else if(retval & OPERATOR_FINISHED) { op->customdata= NULL; if(ot->flag & OPTYPE_UNDO) @@ -1227,6 +1236,26 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) /* screen context changes here */ action |= wm_handler_fileselect_call(C, handlers, handler, event); } + else if(handler->dropboxes) { + if(event->type==EVT_DROP) { + wmDropBox *drop= handler->dropboxes->first; + for(; drop; drop= drop->next) { + /* other drop custom types allowed */ + if(event->custom==EVT_DATA_LISTBASE) { + ListBase *lb= (ListBase *)event->customdata; + wmDrag *drag; + for(drag= lb->first; drag; drag= drag->next) { + if(drop->poll(C, drag, event)) { + drop->copy(drag, drop); + + wm_operator_invoke(C, drop->ot, event, drop->ptr, NULL); + action |= WM_HANDLER_BREAK; + } + } + } + } + } + } else { /* modal, swallows all */ action |= wm_handler_operator_call(C, handlers, handler, event, NULL); @@ -1353,13 +1382,51 @@ static void wm_paintcursor_test(bContext *C, wmEvent *event) } } +static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *event) +{ + if(wm->drags.first==NULL) return; + + if(event->type==MOUSEMOVE) + win->screen->do_draw_drag= 1; + else if(event->type==ESCKEY) { + BLI_freelistN(&wm->drags); + win->screen->do_draw_drag= 1; + } + 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_LISTBASE; + event->customdata= &wm->drags; + event->customdatafree= 1; + + /* clear drop icon */ + win->screen->do_draw_drag= 1; + + /* restore cursor (disabled, see wm_dragdrop.c) */ + // WM_cursor_restore(win); + } + + /* overlap fails otherwise */ + if(win->screen->do_draw_drag) + if(win->drawmethod == USER_DRAW_OVERLAP) + win->screen->do_draw= 1; + +} + /* 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; - for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) { + for(win= wm->windows.first; win; win= win->next) { wmEvent *event; if( win->screen==NULL ) @@ -1386,6 +1453,9 @@ void wm_event_do_handlers(bContext *C) if(CTX_wm_window(C)==NULL) return; + /* 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); @@ -1410,8 +1480,16 @@ void wm_event_do_handlers(bContext *C) for(ar=sa->regionbase.first; ar; ar= ar->next) { if(wm_event_inside_i(event, &ar->winrct)) { CTX_wm_region_set(C, ar); + + /* does polls for drop regions and checks uibuts */ + /* need to be here to make sure region context is true */ + if(event->type==MOUSEMOVE) { + wm_region_mouse_co(C, event); + wm_drags_check_ops(C, event); + } + action |= wm_handlers_do(C, event, &ar->handlers); - + doit |= (BLI_in_rcti(&ar->winrct, event->x, event->y)); if(action & WM_HANDLER_BREAK) @@ -1657,6 +1735,25 @@ void WM_event_remove_ui_handler(ListBase *handlers, wmUIHandlerFunc func, wmUIHa } } +wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase *dropboxes) +{ + wmEventHandler *handler; + + /* only allow same dropbox once */ + for(handler= handlers->first; handler; handler= handler->next) + if(handler->dropboxes==dropboxes) + return handler; + + handler= MEM_callocN(sizeof(wmEventHandler), "dropbox handler"); + + /* 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) { wmEventHandler *handler, *nexthandler; @@ -1705,7 +1802,6 @@ int WM_modal_tweak_exit(wmEvent *evt, int tweak_event) return 0; } - /* ********************* ghost stuff *************** */ static int convert_key(GHOST_TKey key) @@ -1804,10 +1900,43 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) } } +/* imperfect but probably usable... draw/enable drags to other windows */ +static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *evt) +{ + short mx= evt->x, my= evt->y; + + if(wm->windows.first== wm->windows.last) + return NULL; + + /* top window bar... */ + if(mx<0 || my<0 || mx>win->sizex || my>win->sizey+30) { + wmWindow *owin; + + /* to desktop space */ + mx+= win->posx; + my+= win->posy; + + /* check other windows to see if it has mouse inside */ + for(owin= wm->windows.first; owin; owin= owin->next) { + if(owin!=win) { + if(mx-owin->posx >= 0 && my-owin->posy >= 0 && + mx-owin->posx <= owin->sizex && my-owin->posy <= owin->sizey) { + evt->x= mx-owin->posx; + evt->y= my-owin->posy; + + return owin; + } + } + } + } + return NULL; +} /* windows store own event queues, no bContext here */ -void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) +/* time is in 1000s of seconds, from ghost */ +void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int time, void *customdata) { + wmWindow *owin; wmEvent event, *evt= win->eventstate; /* initialize and copy state (only mouse x y and modifiers) */ @@ -1818,20 +1947,42 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) case GHOST_kEventCursorMove: { if(win->active) { GHOST_TEventCursorData *cd= customdata; + #if defined(__APPLE__) && defined(GHOST_COCOA) //Cocoa already uses coordinates with y=0 at bottom, and returns inwindow coordinates on mouse moved event - event.type= MOUSEMOVE; - event.x= evt->x = cd->x; - event.y = evt->y = cd->y; + evt->x= cd->x; + evt->y= cd->y; #else int cx, cy; + GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); - event.type= MOUSEMOVE; - event.x= evt->x= cx; - event.y= evt->y= (win->sizey-1) - cy; + evt->x= cx; + evt->y= (win->sizey-1) - cy; #endif + + event.x= evt->x; + event.y= evt->y; + + event.type= MOUSEMOVE; + update_tablet_data(win, &event); wm_event_add(win, &event); + + /* 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= *(owin->eventstate); + + oevent.x= event.x; + oevent.y= event.y; + oevent.type= MOUSEMOVE; + + *(owin->eventstate)= oevent; + update_tablet_data(owin, &oevent); + wm_event_add(owin, &oevent); + } + } break; } @@ -1888,8 +2039,23 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) else event.type= MIDDLEMOUSE; - update_tablet_data(win, &event); - wm_event_add(win, &event); + /* 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; + + update_tablet_data(owin, &oevent); + wm_event_add(owin, &oevent); + } + else { + update_tablet_data(win, &event); + wm_event_add(win, &event); + } break; } @@ -1943,7 +2109,7 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) /* if test_break set, it catches this. XXX Keep global for now? */ if(event.type==ESCKEY) G.afbreek= 1; - + wm_event_add(win, &event); break; @@ -1980,6 +2146,7 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) wm_event_add(win, &event); break; + } } diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index e94aab7ab89..47d8c8d9831 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -101,11 +101,24 @@ wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type) void WM_gesture_end(bContext *C, wmGesture *gesture) { - BLI_remlink(&CTX_wm_window(C)->gesture, gesture); + wmWindow *win= CTX_wm_window(C); + + if(win->tweak==gesture) + win->tweak= NULL; + BLI_remlink(&win->gesture, gesture); MEM_freeN(gesture->customdata); MEM_freeN(gesture); } +void WM_gestures_remove(bContext *C) +{ + wmWindow *win= CTX_wm_window(C); + + while(win->gesture.first) + WM_gesture_end(C, win->gesture.first); +} + + /* tweak and line gestures */ #define TWEAK_THRESHOLD 10 int wm_gesture_evaluate(bContext *C, wmGesture *gesture) @@ -338,3 +351,4 @@ void wm_gesture_tag_redraw(bContext *C) ED_region_tag_redraw(ar); } + diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 48164b5ac16..93612430967 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -227,6 +227,7 @@ void WM_exit(bContext *C) } } wm_operatortype_free(); + wm_dropbox_free(); WM_menutype_free(); /* all non-screen and non-space stuff editors did, like editmode */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 2f2aebbc525..8f088efe8a8 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2123,7 +2123,6 @@ static void tweak_gesture_modal(bContext *C, wmEvent *event) wm_event_add(window, &event); WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */ - window->tweak= NULL; } break; @@ -2133,7 +2132,6 @@ static void tweak_gesture_modal(bContext *C, wmEvent *event) case MIDDLEMOUSE: if(gesture->event_type==event->type) { WM_gesture_end(C, gesture); - window->tweak= NULL; /* when tweak fails we should give the other keymap entries a chance */ event->val= KM_RELEASE; @@ -2142,7 +2140,6 @@ static void tweak_gesture_modal(bContext *C, wmEvent *event) default: if(!ISTIMER(event->type)) { WM_gesture_end(C, gesture); - window->tweak= NULL; } break; } @@ -2155,16 +2152,16 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action) if(win->tweak==NULL) { if(CTX_wm_region(C)) { - if(event->val==KM_PRESS) { // pressed + if(event->val==KM_PRESS) { if( ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) ) win->tweak= WM_gesture_new(C, event, WM_GESTURE_TWEAK); } } } else { - if(action & WM_HANDLER_BREAK) { + /* no tweaks if event was handled */ + if((action & WM_HANDLER_BREAK)) { WM_gesture_end(C, win->tweak); - win->tweak= NULL; } else tweak_gesture_modal(C, event); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index aaa24957715..ed593cb8dcd 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -554,6 +554,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) bContext *C= private; wmWindowManager *wm= CTX_wm_manager(C); GHOST_TEventType type= GHOST_GetEventType(evt); + int time= GHOST_GetEventTime(evt); if (type == GHOST_kEventQuit) { WM_exit(C); @@ -578,7 +579,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) switch(type) { case GHOST_kEventWindowDeactivate: - wm_event_add_ghostevent(win, type, data); + wm_event_add_ghostevent(wm, win, type, time, data); win->active= 0; /* XXX */ break; case GHOST_kEventWindowActivate: @@ -595,19 +596,19 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) kdata.ascii= 0; if (win->eventstate->shift && !query_qual('s')) { kdata.key= GHOST_kKeyLeftShift; - wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata); + wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } if (win->eventstate->ctrl && !query_qual('c')) { kdata.key= GHOST_kKeyLeftControl; - wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata); + wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } if (win->eventstate->alt && !query_qual('a')) { kdata.key= GHOST_kKeyLeftAlt; - wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata); + wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } if (win->eventstate->oskey && !query_qual('C')) { kdata.key= GHOST_kKeyCommand; - wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata); + wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } /* keymodifier zero, it hangs on hotkeys that open windows otherwise */ win->eventstate->keymodifier= 0; @@ -625,6 +626,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) win->eventstate->y= (win->sizey-1) - cy; #endif + win->addmousemove= 1; /* enables highlighted buttons */ + wm_window_make_drawable(C, win); break; } @@ -679,7 +682,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) win->sizey= sizey; win->posx= posx; win->posy= posy; - + /* debug prints */ if(0) { state = GHOST_GetWindowState(win->ghostwin); @@ -711,8 +714,29 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) } break; } + case GHOST_kEventDraggingDropDone: + { + wmEvent event= *(win->eventstate); /* copy last state, like mouse coords */ + + /* make blender drop event with custom data pointing to wm drags */ + event.type= EVT_DROP; + event.custom= EVT_DATA_LISTBASE; + event.customdata= &wm->drags; + + printf("Drop detected\n"); + + /* add drag data to wm for paths: */ + /* need icon type, some dropboxes check for that... see filesel code for this */ + // WM_event_start_drag(C, icon, WM_DRAG_PATH, void *poin, 0.0); + /* void poin should point to string, it makes a copy */ + + wm_event_add(win, &event); + + break; + } + default: - wm_event_add_ghostevent(win, type, data); + wm_event_add_ghostevent(wm, win, type, time, data); break; } diff --git a/source/blender/windowmanager/wm_cursors.h b/source/blender/windowmanager/wm_cursors.h index 3d1b49983ed..41772ffc661 100644 --- a/source/blender/windowmanager/wm_cursors.h +++ b/source/blender/windowmanager/wm_cursors.h @@ -47,6 +47,7 @@ enum { CURSOR_STD, CURSOR_NONE, CURSOR_PENCIL, + CURSOR_COPY, }; diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index 3d7cb3fbad1..58778c5acbf 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -64,6 +64,9 @@ typedef struct wmEventHandler { /* fileselect handler re-uses modal operator data */ struct bScreen *filescreen; /* screen it started in, to validate exec */ + /* drop box handler */ + ListBase *dropboxes; + } wmEventHandler; @@ -89,12 +92,16 @@ void wm_event_free_handler (wmEventHandler *handler); /* goes over entire hierarchy: events -> window -> screen -> area -> region */ void wm_event_do_handlers (bContext *C); -void wm_event_add_ghostevent (wmWindow *win, int type, void *customdata); +void wm_event_add_ghostevent (wmWindowManager *wm, wmWindow *win, int type, int time, void *customdata); void wm_event_do_notifiers (bContext *C); /* wm_keymap.c */ +/* wm_dropbox.c */ +void wm_dropbox_free(void); +void wm_drags_check_ops(bContext *C, wmEvent *event); +void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect); #endif /* WM_EVENT_SYSTEM_H */ diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index a90eb702069..be0f5abbc47 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -39,6 +39,7 @@ #define EVT_DATA_TABLET 1 #define EVT_DATA_GESTURE 2 #define EVT_DATA_TIMER 3 +#define EVT_DATA_LISTBASE 4 /* tablet active, matches GHOST_TTabletMode */ #define EVT_TABLET_NONE 0 @@ -265,6 +266,7 @@ /* event->type */ #define EVT_BUT_OPEN 0x5021 #define EVT_MODAL_MAP 0x5022 +#define EVT_DROP 0x5023 /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ #define GESTURE_MODAL_CANCEL 1 diff --git a/source/nan_compile.mk b/source/nan_compile.mk index 3255f102ab7..0f9ee0669e0 100644 --- a/source/nan_compile.mk +++ b/source/nan_compile.mk @@ -94,8 +94,8 @@ ifeq ($(OS),darwin) CCFLAGS += -arch $(MACOSX_ARCHITECTURE) #-isysroot $(MACOSX_SDK) -mmacosx-version-min=$(MACOSX_MIN_VERS) ifeq ($(MACOSX_ARCHITECTURE), $(findstring $(MACOSX_ARCHITECTURE), "i386 x86_64")) - REL_CFLAGS += -O2 -ftree-vectorize -msse -msse2 -msse3 - REL_CCFLAGS += -O2 -ftree-vectorize -msse -msse2 -msse3 + REL_CFLAGS += -ftree-vectorize -msse -msse2 -msse3 + REL_CCFLAGS += -ftree-vectorize -msse -msse2 -msse3 endif ifeq ($(MACOSX_ARCHITECTURE), x86_64) diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index ac40b9cb807..38af4bd24d5 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -266,7 +266,7 @@ ifndef CONFIG_GUESS export NAN_SAMPLERATE_LIBS ?= $(NAN_SAMPLERATE)/lib/libsamplerate.a # enable building with Cocoa - export WITH_COCOA ?= true + export WITH_COCOA ?= false export USE_QTKIT ?= false # use cocoa and qtkit for 64bit builds ifeq (64, $(findstring 64, $(MACOSX_ARCHITECTURE))) |