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