|
Blender
V2.59
|
00001 /* 00002 * $Id: wm_dragdrop.c 35179 2011-02-25 14:04:21Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2010 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * 00024 * Contributor(s): Blender Foundation 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include <string.h> 00035 00036 #include "DNA_windowmanager_types.h" 00037 #include "DNA_screen_types.h" 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "BLI_blenlib.h" 00042 00043 #include "BIF_gl.h" 00044 #include "BIF_glutil.h" 00045 00046 #include "BKE_blender.h" 00047 #include "BKE_context.h" 00048 #include "BKE_idprop.h" 00049 #include "BKE_library.h" 00050 #include "BKE_main.h" 00051 #include "BKE_screen.h" 00052 #include "BKE_global.h" 00053 00054 #include "IMB_imbuf_types.h" 00055 #include "IMB_imbuf.h" 00056 00057 #include "UI_interface.h" 00058 #include "UI_interface_icons.h" 00059 00060 #include "WM_api.h" 00061 #include "WM_types.h" 00062 #include "wm_event_system.h" 00063 #include "wm.h" 00064 00065 00066 /* ****************************************************** */ 00067 00068 static ListBase dropboxes= {NULL, NULL}; 00069 00070 /* drop box maps are stored global for now */ 00071 /* these are part of blender's UI/space specs, and not like keymaps */ 00072 /* when editors become configurable, they can add own dropbox definitions */ 00073 00074 typedef struct wmDropBoxMap { 00075 struct wmDropBoxMap *next, *prev; 00076 00077 ListBase dropboxes; 00078 short spaceid, regionid; 00079 char idname[KMAP_MAX_NAME]; 00080 00081 } wmDropBoxMap; 00082 00083 /* spaceid/regionid is zero for window drop maps */ 00084 ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid) 00085 { 00086 wmDropBoxMap *dm; 00087 00088 for(dm= dropboxes.first; dm; dm= dm->next) 00089 if(dm->spaceid==spaceid && dm->regionid==regionid) 00090 if(0==strncmp(idname, dm->idname, KMAP_MAX_NAME)) 00091 return &dm->dropboxes; 00092 00093 dm= MEM_callocN(sizeof(struct wmDropBoxMap), "dropmap list"); 00094 BLI_strncpy(dm->idname, idname, KMAP_MAX_NAME); 00095 dm->spaceid= spaceid; 00096 dm->regionid= regionid; 00097 BLI_addtail(&dropboxes, dm); 00098 00099 return &dm->dropboxes; 00100 } 00101 00102 00103 00104 wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, wmEvent *), 00105 void (*copy)(wmDrag *, wmDropBox *)) 00106 { 00107 wmDropBox *drop= MEM_callocN(sizeof(wmDropBox), "wmDropBox"); 00108 00109 drop->poll= poll; 00110 drop->copy= copy; 00111 drop->ot= WM_operatortype_find(idname, 0); 00112 drop->opcontext= WM_OP_INVOKE_DEFAULT; 00113 00114 if(drop->ot==NULL) { 00115 MEM_freeN(drop); 00116 printf("Error: dropbox with unknown operator: %s\n", idname); 00117 return NULL; 00118 } 00119 WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname); 00120 00121 BLI_addtail(lb, drop); 00122 00123 return drop; 00124 } 00125 00126 void wm_dropbox_free(void) 00127 { 00128 wmDropBoxMap *dm; 00129 00130 for(dm= dropboxes.first; dm; dm= dm->next) { 00131 wmDropBox *drop; 00132 00133 for(drop= dm->dropboxes.first; drop; drop= drop->next) { 00134 if(drop->ptr) { 00135 WM_operator_properties_free(drop->ptr); 00136 MEM_freeN(drop->ptr); 00137 } 00138 } 00139 BLI_freelistN(&dm->dropboxes); 00140 } 00141 00142 BLI_freelistN(&dropboxes); 00143 } 00144 00145 /* *********************************** */ 00146 00147 /* note that the pointer should be valid allocated and not on stack */ 00148 wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value) 00149 { 00150 wmWindowManager *wm= CTX_wm_manager(C); 00151 wmDrag *drag= MEM_callocN(sizeof(struct wmDrag), "new drag"); 00152 00153 /* keep track of future multitouch drag too, add a mousepointer id or so */ 00154 /* if multiple drags are added, they're drawn as list */ 00155 00156 BLI_addtail(&wm->drags, drag); 00157 drag->icon= icon; 00158 drag->type= type; 00159 if(type==WM_DRAG_PATH) 00160 BLI_strncpy(drag->path, poin, FILE_MAX); 00161 else 00162 drag->poin= poin; 00163 drag->value= value; 00164 00165 return drag; 00166 } 00167 00168 void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy) 00169 { 00170 drag->imb= imb; 00171 drag->scale= scale; 00172 drag->sx= sx; 00173 drag->sy= sy; 00174 } 00175 00176 00177 static const char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, wmEvent *event) 00178 { 00179 wmEventHandler *handler= handlers->first; 00180 for(; handler; handler= handler->next) { 00181 if(handler->dropboxes) { 00182 wmDropBox *drop= handler->dropboxes->first; 00183 for(; drop; drop= drop->next) { 00184 if(drop->poll(C, drag, event)) 00185 return drop->ot->name; 00186 } 00187 } 00188 } 00189 return NULL; 00190 } 00191 00192 /* return active operator name when mouse is in box */ 00193 static const char *wm_dropbox_active(bContext *C, wmDrag *drag, wmEvent *event) 00194 { 00195 wmWindow *win= CTX_wm_window(C); 00196 ScrArea *sa= CTX_wm_area(C); 00197 ARegion *ar= CTX_wm_region(C); 00198 const char *name; 00199 00200 name= dropbox_active(C, &win->handlers, drag, event); 00201 if(name) return name; 00202 00203 name= dropbox_active(C, &sa->handlers, drag, event); 00204 if(name) return name; 00205 00206 name= dropbox_active(C, &ar->handlers, drag, event); 00207 if(name) return name; 00208 00209 return NULL; 00210 } 00211 00212 00213 static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event) 00214 { 00215 wmWindow *win= CTX_wm_window(C); 00216 00217 /* for multiwin drags, we only do this if mouse inside */ 00218 if(event->x<0 || event->y<0 || event->x>win->sizex || event->y>win->sizey) 00219 return; 00220 00221 drag->opname[0]= 0; 00222 00223 /* check buttons (XXX todo rna and value) */ 00224 if( UI_but_active_drop_name(C) ) { 00225 strcpy(drag->opname, "Paste name"); 00226 } 00227 else { 00228 const char *opname= wm_dropbox_active(C, drag, event); 00229 00230 if(opname) { 00231 BLI_strncpy(drag->opname, opname, FILE_MAX); 00232 // WM_cursor_modal(win, CURSOR_COPY); 00233 } 00234 // else 00235 // WM_cursor_restore(win); 00236 /* unsure about cursor type, feels to be too much */ 00237 } 00238 } 00239 00240 /* called in inner handler loop, region context */ 00241 void wm_drags_check_ops(bContext *C, wmEvent *event) 00242 { 00243 wmWindowManager *wm= CTX_wm_manager(C); 00244 wmDrag *drag; 00245 00246 for(drag= wm->drags.first; drag; drag= drag->next) { 00247 wm_drop_operator_options(C, drag, event); 00248 } 00249 } 00250 00251 /* ************** draw ***************** */ 00252 00253 static void wm_drop_operator_draw(char *name, int x, int y) 00254 { 00255 int width= UI_GetStringWidth(name); 00256 00257 glColor4ub(0, 0, 0, 50); 00258 00259 uiSetRoundBox(15+16); 00260 uiRoundBox(x, y, x + width + 8, y + 15, 4); 00261 00262 glColor4ub(255, 255, 255, 255); 00263 UI_DrawString(x+4, y+4, name); 00264 } 00265 00266 static const char *wm_drag_name(wmDrag *drag) 00267 { 00268 switch(drag->type) { 00269 case WM_DRAG_ID: 00270 { 00271 ID *id= (ID *)drag->poin; 00272 return id->name+2; 00273 } 00274 case WM_DRAG_PATH: 00275 return drag->path; 00276 case WM_DRAG_NAME: 00277 return (char *)drag->path; 00278 } 00279 return ""; 00280 } 00281 00282 static void drag_rect_minmax(rcti *rect, int x1, int y1, int x2, int y2) 00283 { 00284 if(rect->xmin > x1) 00285 rect->xmin= x1; 00286 if(rect->xmax < x2) 00287 rect->xmax= x2; 00288 if(rect->ymin > y1) 00289 rect->ymin= y1; 00290 if(rect->ymax < y2) 00291 rect->ymax= y2; 00292 } 00293 00294 /* called in wm_draw.c */ 00295 /* if rect set, do not draw */ 00296 void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) 00297 { 00298 wmWindowManager *wm= CTX_wm_manager(C); 00299 wmDrag *drag; 00300 int cursorx, cursory, x, y; 00301 00302 cursorx= win->eventstate->x; 00303 cursory= win->eventstate->y; 00304 if(rect) { 00305 rect->xmin= rect->xmax= cursorx; 00306 rect->ymin= rect->ymax= cursory; 00307 } 00308 00309 /* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */ 00310 glEnable(GL_BLEND); 00311 for(drag= wm->drags.first; drag; drag= drag->next) { 00312 00313 /* image or icon */ 00314 if(drag->imb) { 00315 x= cursorx - drag->sx/2; 00316 y= cursory - drag->sy/2; 00317 00318 if(rect) 00319 drag_rect_minmax(rect, x, y, x+drag->sx, y+drag->sy); 00320 else { 00321 glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */ 00322 glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, drag->imb->rect, drag->scale, drag->scale); 00323 } 00324 } 00325 else { 00326 x= cursorx - 8; 00327 y= cursory - 2; 00328 00329 /* icons assumed to be 16 pixels */ 00330 if(rect) 00331 drag_rect_minmax(rect, x, y, x+16, y+16); 00332 else 00333 UI_icon_draw_aspect(x, y, drag->icon, 1.0, 0.8); 00334 } 00335 00336 /* item name */ 00337 if(drag->imb) { 00338 x= cursorx - drag->sx/2; 00339 y= cursory - drag->sy/2 - 16; 00340 } 00341 else { 00342 x= cursorx + 10; 00343 y= cursory + 1; 00344 } 00345 00346 if(rect) { 00347 int w= UI_GetStringWidth(wm_drag_name(drag)); 00348 drag_rect_minmax(rect, x, y, x+w, y+16); 00349 } 00350 else { 00351 glColor4ub(255, 255, 255, 255); 00352 UI_DrawString(x, y, wm_drag_name(drag)); 00353 } 00354 00355 /* operator name with roundbox */ 00356 if(drag->opname[0]) { 00357 if(drag->imb) { 00358 x= cursorx - drag->sx/2; 00359 y= cursory + drag->sy/2 + 4; 00360 } 00361 else { 00362 x= cursorx - 8; 00363 y= cursory + 16; 00364 } 00365 00366 if(rect) { 00367 int w= UI_GetStringWidth(wm_drag_name(drag)); 00368 drag_rect_minmax(rect, x, y, x+w, y+16); 00369 } 00370 else 00371 wm_drop_operator_draw(drag->opname, x, y); 00372 00373 } 00374 } 00375 glDisable(GL_BLEND); 00376 }