Todo item #19816: Wave modifier does not affect Curve Paths
[blender.git] / source / blender / editors / interface / interface_templates.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Blender Foundation 2009.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include <stdlib.h>
26 #include <stddef.h>
27 #include <string.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "DNA_scene_types.h"
32 #include "DNA_userdef_types.h"
33
34 #include "BLI_string.h"
35 #include "BLI_utildefines.h"
36
37 #include "BKE_animsys.h"
38 #include "BKE_colortools.h"
39 #include "BKE_context.h"
40 #include "BKE_global.h"
41 #include "BKE_library.h"
42 #include "BKE_main.h"
43 #include "BKE_object.h"
44 #include "BKE_material.h"
45 #include "BKE_texture.h"
46 #include "BKE_report.h"
47 #include "BKE_displist.h"
48
49 #include "ED_screen.h"
50 #include "ED_render.h"
51
52 #include "RNA_access.h"
53
54 #include "WM_api.h"
55 #include "WM_types.h"
56
57 #include "UI_interface.h"
58 #include "interface_intern.h"
59
60 #include "BLF_api.h"
61
62 void ui_template_fix_linking(void)
63 {
64 }
65
66 /********************** Header Template *************************/
67
68 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
69 {
70         uiBlock *block;
71
72         block= uiLayoutAbsoluteBlock(layout);
73         if(menus) ED_area_header_standardbuttons(C, block, 0);
74         else ED_area_header_switchbutton(C, block, 0);
75 }
76
77 /********************** Search Callbacks *************************/
78
79 typedef struct TemplateID {
80         PointerRNA ptr;
81         PropertyRNA *prop;
82
83         ListBase *idlb;
84         int prv_rows, prv_cols;
85 } TemplateID;
86
87 /* Search browse menu, assign  */
88 static void id_search_call_cb(bContext *C, void *arg_template, void *item)
89 {
90         TemplateID *template= (TemplateID*)arg_template;
91
92         /* ID */
93         if(item) {
94                 PointerRNA idptr;
95
96                 RNA_id_pointer_create(item, &idptr);
97                 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
98                 RNA_property_update(C, &template->ptr, template->prop);
99         }
100 }
101
102 /* ID Search browse menu, do the search */
103 static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
104 {
105         TemplateID *template= (TemplateID*)arg_template;
106         ListBase *lb= template->idlb;
107         ID *id, *id_from= template->ptr.id.data;
108         int iconid;
109         int flag= RNA_property_flag(template->prop);
110
111         /* ID listbase */
112         for(id= lb->first; id; id= id->next) {
113                 if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
114
115                         /* use filter */
116                         if(RNA_property_type(template->prop)==PROP_POINTER) {
117                                 PointerRNA ptr;
118                                 RNA_id_pointer_create(id, &ptr);
119                                 if(RNA_property_pointer_poll(&template->ptr, template->prop, &ptr)==0)
120                                         continue;
121                         }
122
123                         /* hide dot-datablocks, but only if filter does not force it visible */
124                         if(U.uiflag & USER_HIDE_DOT)
125                                 if ((id->name[2]=='.') && (str[0] != '.'))
126                                         continue;
127
128                         if(BLI_strcasestr(id->name+2, str)) {
129                                 char name_ui[32];
130                                 name_uiprefix_id(name_ui, id);
131
132                                 iconid= ui_id_icon_get((bContext*)C, id, 1);
133
134                                 if(!uiSearchItemAdd(items, name_ui, id, iconid))
135                                         break;
136                         }
137                 }
138         }
139 }
140
141 /* ID Search browse menu, open */
142 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
143 {
144         static char search[256];
145         static TemplateID template;
146         PointerRNA idptr;
147         wmEvent event;
148         wmWindow *win= CTX_wm_window(C);
149         uiBlock *block;
150         uiBut *but;
151         
152         /* clear initial search string, then all items show */
153         search[0]= 0;
154         /* arg_litem is malloced, can be freed by parent button */
155         template= *((TemplateID*)arg_litem);
156         
157         /* get active id for showing first item */
158         idptr= RNA_property_pointer_get(&template.ptr, template.prop);
159
160         block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
161         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
162         
163         /* preview thumbnails */
164         if (template.prv_rows > 0 && template.prv_cols > 0) {
165                 int w = 96 * template.prv_cols;
166                 int h = 96 * template.prv_rows + 20;
167                 
168                 /* fake button, it holds space for search items */
169                 uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
170                 
171                 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, w, 19, template.prv_rows, template.prv_cols, "");
172                 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
173         }
174         /* list view */
175         else {
176                 /* fake button, it holds space for search items */
177                 uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
178                 
179                 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, "");
180                 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
181         }
182                 
183         
184         uiBoundsBlock(block, 6);
185         uiBlockSetDirection(block, UI_DOWN);    
186         uiEndBlock(C, block);
187         
188         event= *(win->eventstate);      /* XXX huh huh? make api call */
189         event.type= EVT_BUT_OPEN;
190         event.val= KM_PRESS;
191         event.customdata= but;
192         event.customdatafree= FALSE;
193         wm_event_add(win, &event);
194         
195         return block;
196 }
197
198 /************************ ID Template ***************************/
199 /* This is for browsing and editing the ID-blocks used */
200
201 /* for new/open operators */
202 void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
203 {
204         TemplateID *template;
205         ARegion *ar= CTX_wm_region(C);
206         uiBlock *block;
207         uiBut *but;
208
209         memset(ptr, 0, sizeof(*ptr));
210         *prop= NULL;
211
212         if(!ar)
213                 return;
214
215         for(block=ar->uiblocks.first; block; block=block->next) {
216                 for(but=block->buttons.first; but; but= but->next) {
217                         /* find the button before the active one */
218                         if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
219                                 if(but->func_argN) {
220                                         template= but->func_argN;
221                                         *ptr= template->ptr;
222                                         *prop= template->prop;
223                                         return;
224                                 }
225                         }
226                 }
227         }
228 }
229
230
231 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
232 {
233         TemplateID *template= (TemplateID*)arg_litem;
234         PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
235         ID *id= idptr.data, *newid;
236         int event= GET_INT_FROM_POINTER(arg_event);
237         
238         switch(event) {
239                 case UI_ID_BROWSE:
240                 case UI_ID_PIN:
241                         printf("warning, id event %d shouldnt come here\n", event);
242                         break;
243                 case UI_ID_OPEN:
244                 case UI_ID_ADD_NEW:
245                         /* these call uiIDContextPropertySet */
246                         break;
247                 case UI_ID_DELETE:
248                         memset(&idptr, 0, sizeof(idptr));
249                         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
250                         RNA_property_update(C, &template->ptr, template->prop);
251
252                         if(id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */
253                                 id->us= 0;
254
255                         break;
256                 case UI_ID_FAKE_USER:
257                         if(id) {
258                                 if(id->flag & LIB_FAKEUSER) id_us_plus(id);
259                                 else id_us_min(id);
260                         }
261                         else return;
262                         break;
263                 case UI_ID_LOCAL:
264                         if(id) {
265                                 if(id_make_local(id, 0)) {
266                                         /* reassign to get get proper updates/notifiers */
267                                         idptr= RNA_property_pointer_get(&template->ptr, template->prop);
268                                         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
269                                         RNA_property_update(C, &template->ptr, template->prop);
270                                 }
271                         }
272                         break;
273                 case UI_ID_ALONE:
274                         if(id) {
275                                 /* make copy */
276                                 if(id_copy(id, &newid, 0) && newid) {
277                                         /* copy animation actions too */
278                                         BKE_copy_animdata_id_action(id);
279                                         /* us is 1 by convention, but RNA_property_pointer_set
280                                            will also incremement it, so set it to zero */
281                                         newid->us= 0;
282
283                                         /* assign copy */
284                                         RNA_id_pointer_create(newid, &idptr);
285                                         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
286                                         RNA_property_update(C, &template->ptr, template->prop);
287                                 }
288                         }
289                         break;
290 #if 0
291                 case UI_ID_AUTO_NAME:
292                         break;
293 #endif
294         }
295 }
296
297 static const char *template_id_browse_tip(StructRNA *type)
298 {
299         if(type) {
300                 switch(RNA_type_to_ID_code(type)) {
301                         case ID_SCE: return "Browse Scene to be linked";
302                         case ID_OB: return "Browse Object to be linked";
303                         case ID_ME: return "Browse Mesh Data to be linked";
304                         case ID_CU: return "Browse Curve Data to be linked";
305                         case ID_MB: return "Browse MetaBall Data to be linked";
306                         case ID_MA: return "Browse Material to be linked";
307                         case ID_TE: return "Browse Texture to be linked";
308                         case ID_IM: return "Browse Image to be linked";
309                         case ID_LA: return "Browse Lattice Data to be linked";
310                         case ID_CA: return "Browse Camera Data to be linked";
311                         case ID_WO: return "Browse World Settings to be linked";
312                         case ID_SCR: return "Choose Screen lay-out";
313                         case ID_TXT: return "Browse Text to be linked";
314                         case ID_SO: return "Browse Sound to be linked";
315                         case ID_AR: return "Browse Armature data to be linked";
316                         case ID_AC: return "Browse Action to be linked";
317                         case ID_NT: return "Browse Node Tree to be linked";
318                         case ID_BR: return "Browse Brush to be linked";
319                         case ID_PA: return "Browse Particle System to be linked";
320                         case ID_GD: return "Browse Grease Pencil Data to be linked";
321                 }
322         }
323         return "Browse ID data to be linked";
324 }
325
326 static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, const char *newop, const char *openop, const char *unlinkop)
327 {
328         uiBut *but;
329         uiBlock *block;
330         PointerRNA idptr;
331         ListBase *lb;
332         ID *id, *idfrom;
333
334         idptr= RNA_property_pointer_get(&template->ptr, template->prop);
335         id= idptr.data;
336         idfrom= template->ptr.id.data;
337         lb= template->idlb;
338
339         block= uiLayoutGetBlock(layout);
340         uiBlockBeginAlign(block);
341
342         if(idptr.type)
343                 type= idptr.type;
344
345         if(flag & UI_ID_PREVIEWS) {
346
347                 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, template_id_browse_tip(type));
348                 if(type) {
349                         but->icon= RNA_struct_ui_icon(type);
350                         if (id) but->icon = ui_id_icon_get(C, id, 1);
351                         uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW);
352                 }
353                 if((idfrom && idfrom->lib))
354                         uiButSetFlag(but, UI_BUT_DISABLED);
355                 
356                 
357                 uiLayoutRow(layout, 1);
358         } else 
359                 
360         if(flag & UI_ID_BROWSE) {
361                 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, template_id_browse_tip(type));
362                 if(type) {
363                         but->icon= RNA_struct_ui_icon(type);
364                         /* default dragging of icon for id browse buttons */
365                         uiButSetDragID(but, id);
366                         uiButSetFlag(but, UI_HAS_ICON|UI_ICON_LEFT);
367                 }
368
369                 if((idfrom && idfrom->lib))
370                         uiButSetFlag(but, UI_BUT_DISABLED);
371         }
372
373         /* text button with name */
374         if(id) {
375                 char name[UI_MAX_NAME_STR];
376                 const short user_alert= (id->us <= 0);
377
378                 //text_idbutton(id, name);
379                 name[0]= '\0';
380                 but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
381                 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
382                 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
383
384                 if(id->lib) {
385                         if(id->flag & LIB_INDIRECT) {
386                                 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
387                                         "Indirect library datablock, cannot change.");
388                                 uiButSetFlag(but, UI_BUT_DISABLED);
389                         }
390                         else {
391                                 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
392                                         "Direct linked library datablock, click to make local.");
393                                 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
394                                         uiButSetFlag(but, UI_BUT_DISABLED);
395                         }
396
397                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
398                 }
399
400                 if(id->us > 1) {
401                         char str[32];
402
403                         sprintf(str, "%d", id->us);
404
405                         if(id->us<10)
406                                 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
407                         else
408                                 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X+10,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
409
410                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
411                         if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib))
412                                 uiButSetFlag(but, UI_BUT_DISABLED);
413                 }
414         
415                 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
416                 
417                 if(id->lib == NULL && !(ELEM4(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT))) {
418                         uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
419                 }
420         }
421         
422         if(flag & UI_ID_ADD_NEW) {
423                 int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
424                 
425                 if(newop) {
426                         but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
427                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
428                 }
429                 else {
430                         but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
431                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
432                 }
433
434                 if((idfrom && idfrom->lib))
435                         uiButSetFlag(but, UI_BUT_DISABLED);
436         }
437
438         if(flag & UI_ID_OPEN) {
439                 int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
440                 
441                 if(openop) {
442                         but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
443                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
444                 }
445                 else {
446                         but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
447                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
448                 }
449
450                 if((idfrom && idfrom->lib))
451                         uiButSetFlag(but, UI_BUT_DISABLED);
452         }
453         
454         /* delete button */
455         if(id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK)==0) {
456                 if(unlinkop) {
457                         but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
458                         /* so we can access the template from operators, font unlinking needs this */
459                         uiButSetNFunc(but, NULL, MEM_dupallocN(template), 0);
460                 }
461                 else {
462                         but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Unlink datablock. Shift + Click to set users to zero, data gets not saved");
463                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
464
465                         if(RNA_property_flag(template->prop) & PROP_NEVER_NULL)
466                                 uiButSetFlag(but, UI_BUT_DISABLED);
467                 }
468
469                 if((idfrom && idfrom->lib))
470                         uiButSetFlag(but, UI_BUT_DISABLED);
471         }
472         
473         uiBlockEndAlign(block);
474 }
475
476 static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols)
477 {
478         TemplateID *template;
479         PropertyRNA *prop;
480         StructRNA *type;
481
482         prop= RNA_struct_find_property(ptr, propname);
483
484         if(!prop || RNA_property_type(prop) != PROP_POINTER) {
485                 printf("uiTemplateID: pointer property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
486                 return;
487         }
488
489         template= MEM_callocN(sizeof(TemplateID), "TemplateID");
490         template->ptr= *ptr;
491         template->prop= prop;
492         template->prv_rows = prv_rows;
493         template->prv_cols = prv_cols;
494
495         if(newop)
496                 flag |= UI_ID_ADD_NEW;
497         if(openop)
498                 flag |= UI_ID_OPEN;
499
500         type= RNA_property_pointer_type(ptr, prop);
501         template->idlb= which_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
502         
503         /* create UI elements for this template
504          *      - template_ID makes a copy of the template data and assigns it to the relevant buttons
505          */
506         if(template->idlb) {
507                 uiLayoutRow(layout, 1);
508                 template_ID(C, layout, template, type, flag, newop, openop, unlinkop);
509         }
510
511         MEM_freeN(template);
512 }
513
514 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
515 {
516         ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0);
517 }
518
519 void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
520 {
521         ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0);
522 }
523
524 void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols)
525 {
526         ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols);
527 }
528
529 /************************ ID Chooser Template ***************************/
530
531 /* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use 
532  *
533  * - propname: property identifier for property that ID-pointer gets stored to
534  * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
535  */
536 void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text)
537 {
538         PropertyRNA *propID, *propType;
539         uiLayout *row;
540         
541         /* get properties... */
542         propID= RNA_struct_find_property(ptr, propname);
543         propType= RNA_struct_find_property(ptr, proptypename);
544
545         if (!propID || RNA_property_type(propID) != PROP_POINTER) {
546                 printf("uiTemplateAnyID: pointer property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
547                 return;
548         }
549         if (!propType || RNA_property_type(propType) != PROP_ENUM) { 
550                 printf("uiTemplateAnyID: pointer-type property not found: %s.%s\n", RNA_struct_identifier(ptr->type), proptypename);
551                 return;
552         }
553         
554         /* Start drawing UI Elements using standard defines */
555         row= uiLayoutRow(layout, 1);
556         
557         /* Label - either use the provided text, or will become "ID-Block:" */
558         if (text)
559                 uiItemL(row, text, ICON_NULL);
560         else
561                 uiItemL(row, "ID-Block:", ICON_NULL);
562         
563         /* ID-Type Selector - just have a menu of icons */
564         // FIXME: the icon-only setting doesn't work when we supply a blank name
565         uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NULL);
566         
567         /* ID-Block Selector - just use pointer widget... */
568         uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NULL);
569 }
570
571 /********************* RNA Path Builder Template ********************/
572
573 /* ---------- */
574
575 /* This is creating/editing RNA-Paths 
576  *
577  * - ptr: struct which holds the path property
578  * - propname: property identifier for property that path gets stored to
579  * - root_ptr: struct that path gets built from
580  */
581 void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text)
582 {
583         PropertyRNA *propPath;
584         uiLayout *row;
585         
586         /* check that properties are valid */
587         propPath= RNA_struct_find_property(ptr, propname);
588         if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
589                 printf("uiTemplatePathBuilder: path property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
590                 return;
591         }
592         
593         /* Start drawing UI Elements using standard defines */
594         row= uiLayoutRow(layout, 1);
595         
596         /* Path (existing string) Widget */
597         uiItemR(row, ptr, propname, 0, text, ICON_RNA);
598         
599         // TODO: attach something to this to make allow searching of nested properties to 'build' the path
600 }
601
602 /************************ Modifier Template *************************/
603
604 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
605
606 #include <string.h>
607
608 #include "DNA_object_force.h"
609
610 #include "BKE_depsgraph.h"
611 #include "BKE_modifier.h"
612 #include "BKE_particle.h"
613
614 #include "ED_util.h"
615
616 #include "BLI_math.h"
617 #include "BLI_listbase.h"
618
619 #include "ED_object.h"
620
621 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
622 {
623         Scene *scene = CTX_data_scene(C);
624         Object *ob = ob_v;
625         ModifierData *md= md_v;
626         int i, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 0);
627
628         /* undo button operation */
629         md->mode ^= eModifierMode_OnCage;
630
631         for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
632                 if(md == md_v) {
633                         if(i >= cageIndex)
634                                 md->mode ^= eModifierMode_OnCage;
635                         break;
636                 }
637         }
638
639         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
640         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
641 }
642
643 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
644 {
645         Object *ob = ob_v;
646         ModifierData *md = md_v;
647         ModifierData *nmd = modifier_new(md->type);
648
649         modifier_copyData(md, nmd);
650         nmd->mode &= ~eModifierMode_Virtual;
651
652         BLI_addhead(&ob->modifiers, nmd);
653         
654         modifier_unique_name(&ob->modifiers, nmd);
655
656         ob->partype = PAROBJECT;
657
658         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
659         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
660
661         ED_undo_push(C, "Modifier convert to real");
662 }
663
664 static int modifier_can_delete(ModifierData *md)
665 {
666         // fluid particle modifier can't be deleted here
667         if(md->type == eModifierType_ParticleSystem)
668                 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
669                         return 0;
670
671         return 1;
672 }
673
674 static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex)
675 {
676         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
677         PointerRNA ptr;
678         uiBut *but;
679         uiBlock *block;
680         uiLayout *box, *column, *row;
681         uiLayout *result= NULL;
682         int isVirtual = (md->mode & eModifierMode_Virtual);
683         char str[128];
684
685         /* create RNA pointer */
686         RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
687
688         column= uiLayoutColumn(layout, 1);
689         uiLayoutSetContextPointer(column, "modifier", &ptr);
690
691         /* rounded header ------------------------------------------------------------------- */
692         box= uiLayoutBox(column);
693         
694         if (isVirtual) {
695                 row= uiLayoutRow(box, 0);
696                 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
697                 block= uiLayoutGetBlock(row);
698                 /* VIRTUAL MODIFIER */
699                 // XXX this is not used now, since these cannot be accessed via RNA
700                 sprintf(str, "%s parent deform", md->name);
701                 uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
702                 
703                 but = uiDefBut(block, BUT, 0, "Make Real", 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Convert virtual modifier to a real modifier");
704                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
705         }
706         else {
707                 /* REAL MODIFIER */
708                 row = uiLayoutRow(box, 0);
709                 block = uiLayoutGetBlock(row);
710                 
711                 uiBlockSetEmboss(block, UI_EMBOSSN);
712                 /* Open/Close .................................  */
713                 uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NULL);
714                 
715                 /* modifier-type icon */
716                 uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
717                 uiBlockSetEmboss(block, UI_EMBOSS);
718                 
719                 /* modifier name */
720                 uiItemR(row, &ptr, "name", 0, "", ICON_NULL);
721                 
722                 /* mode enabling buttons */
723                 uiBlockBeginAlign(block);
724                 /* Softbody not allowed in this situation, enforce! */
725                 if ( ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) 
726                         && (md->type!=eModifierType_Surface) ) 
727                 {
728                         uiItemR(row, &ptr, "show_render", 0, "", ICON_NULL);
729                         uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NULL);
730                         
731                         if (mti->flags & eModifierTypeFlag_SupportsEditmode)
732                                 uiItemR(row, &ptr, "show_in_editmode", 0, "", ICON_NULL);
733                 }
734                 if ((ob->type==OB_MESH) && modifier_couldBeCage(scene, md) && (index <= lastCageIndex)) 
735                 {
736                         /* -- convert to rna ? */
737                         but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, 16, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
738                         if (index < cageIndex)
739                                 uiButSetFlag(but, UI_BUT_DISABLED);
740                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
741                 }
742
743                 /* tesselation point for curve-typed objects */
744                 if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
745                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
746
747                         /* some modifiers could work with pre-tesselated curves only */
748                         if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
749                                 /* add disabled pre-tesselated button, so users could have
750                                    message for this modifiers */
751                                 but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, 16, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "This modifier could be applied on splines' points only");
752                                 uiButSetFlag(but, UI_BUT_DISABLED);
753                         } else if (mti->type != eModifierTypeType_Constructive) {
754                                 /* constructive modifiers tesselates curve before applying */
755                                 uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NULL);
756                         }
757                 }
758
759                 uiBlockEndAlign(block);
760                 
761                 /* Up/Down + Delete ........................... */
762                 uiBlockBeginAlign(block);
763                 uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
764                 uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
765                 uiBlockEndAlign(block);
766                 
767                 uiBlockSetEmboss(block, UI_EMBOSSN);
768                 if (modifier_can_delete(md))
769                         uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
770                 uiBlockSetEmboss(block, UI_EMBOSS);
771         }
772
773         
774         /* modifier settings (under the header) --------------------------------------------------- */
775         if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
776                 /* apply/convert/copy */
777                 box= uiLayoutBox(column);
778                 row= uiLayoutRow(box, 0);
779                 
780                 if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
781                         /* only here obdata, the rest of modifiers is ob level */
782                         uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
783                         
784                         if (md->type==eModifierType_ParticleSystem) {
785                                 ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
786                                 
787                                 if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) {
788                                         if(ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
789                                                 uiItemO(row, "Convert", ICON_NULL, "OBJECT_OT_duplicates_make_real");
790                                         else if(psys->part->ren_as == PART_DRAW_PATH)
791                                                 uiItemO(row, "Convert", ICON_NULL, "OBJECT_OT_modifier_convert");
792                                 }
793                         }
794                         else {
795                                 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
796                                 uiItemEnumO(row, "OBJECT_OT_modifier_apply", "Apply", 0, "apply_as", MODIFIER_APPLY_DATA);
797                                 
798                                 if (modifier_sameTopology(md))
799                                         uiItemEnumO(row, "OBJECT_OT_modifier_apply", "Apply as Shape", 0, "apply_as", MODIFIER_APPLY_SHAPE);
800                         }
801                         
802                         uiBlockClearButLock(block);
803                         uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
804                         
805                         if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke))
806                                 uiItemO(row, "Copy", ICON_NULL, "OBJECT_OT_modifier_copy");
807                 }
808                 
809                 /* result is the layout block inside the box, that we return so that modifier settings can be drawn */
810                 result= uiLayoutColumn(box, 0);
811                 block= uiLayoutAbsoluteBlock(box);
812         }
813         
814         /* error messages */
815         if(md->error) {
816                 box = uiLayoutBox(column);
817                 row = uiLayoutRow(box, 0);
818                 uiItemL(row, md->error, ICON_ERROR);
819         }
820         
821         return result;
822 }
823
824 uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
825 {
826         Scene *scene = CTX_data_scene(C);
827         Object *ob;
828         ModifierData *md, *vmd;
829         int i, lastCageIndex, cageIndex;
830
831         /* verify we have valid data */
832         if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
833                 printf("uiTemplateModifier: expected modifier on object.\n");
834                 return NULL;
835         }
836
837         ob= ptr->id.data;
838         md= ptr->data;
839
840         if(!ob || !(GS(ob->id.name) == ID_OB)) {
841                 printf("uiTemplateModifier: expected modifier on object.\n");
842                 return NULL;
843         }
844         
845         uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
846         
847         /* find modifier and draw it */
848         cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
849
850         // XXX virtual modifiers are not accesible for python
851         vmd = modifiers_getVirtualModifierList(ob);
852
853         for(i=0; vmd; i++, vmd=vmd->next) {
854                 if(md == vmd)
855                         return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex);
856                 else if(vmd->mode & eModifierMode_Virtual)
857                         i--;
858         }
859
860         return NULL;
861 }
862
863 /************************ Constraint Template *************************/
864
865 #include "DNA_constraint_types.h"
866
867 #include "BKE_action.h"
868 #include "BKE_constraint.h"
869
870 #define REDRAWIPO                                       1
871 #define REDRAWNLA                                       2
872 #define REDRAWBUTSOBJECT                        3               
873 #define REDRAWACTION                            4
874 #define B_CONSTRAINT_TEST                       5
875 #define B_CONSTRAINT_CHANGETARGET       6
876 #define REMAKEIPO                                       8
877 #define B_DIFF                                          9
878
879 void do_constraint_panels(bContext *C, void *ob_pt, int event)
880 {
881         Main *bmain= CTX_data_main(C);
882         Scene *scene= CTX_data_scene(C);
883         Object *ob= (Object *)ob_pt;
884         
885         switch(event) {
886         case B_CONSTRAINT_TEST:
887                 break;  // no handling
888         case B_CONSTRAINT_CHANGETARGET:
889                 if (ob->pose) ob->pose->flag |= POSE_RECALC;    // checks & sorts pose channels
890                 DAG_scene_sort(bmain, scene);
891                 break;
892         default:
893                 break;
894         }
895
896         // note: RNA updates now call this, commenting else it gets called twice.
897         // if there are problems because of this, then rna needs changed update functions.
898         // 
899         // object_test_constraints(ob);
900         // if(ob->pose) update_pose_constraint_flags(ob->pose);
901         
902         if(ob->type==OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
903         else DAG_id_tag_update(&ob->id, OB_RECALC_OB);
904
905         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
906 }
907
908 static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
909 {
910         ED_object_constraint_set_active(ob_v, con_v);
911 }
912
913 /* draw panel showing settings for a constraint */
914 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
915 {
916         bPoseChannel *pchan= get_active_posechannel(ob);
917         bConstraintTypeInfo *cti;
918         uiBlock *block;
919         uiLayout *result= NULL, *col, *box, *row;
920         PointerRNA ptr;
921         char typestr[32];
922         short proxy_protected, xco=0, yco=0;
923         int rb_col;
924
925         /* get constraint typeinfo */
926         cti= constraint_get_typeinfo(con);
927         if (cti == NULL) {
928                 /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
929                 if (con->type == CONSTRAINT_TYPE_NULL)
930                         strcpy(typestr, "Null");
931                 else
932                         strcpy(typestr, "Unknown");
933         }
934         else
935                 strcpy(typestr, cti->name);
936                 
937         /* determine whether constraint is proxy protected or not */
938         if (proxylocked_constraints_owner(ob, pchan))
939                 proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0;
940         else
941                 proxy_protected= 0;
942
943         /* unless button has own callback, it adds this callback to button */
944         block= uiLayoutGetBlock(layout);
945         uiBlockSetHandleFunc(block, do_constraint_panels, ob);
946         uiBlockSetFunc(block, constraint_active_func, ob, con);
947
948         RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
949
950         col= uiLayoutColumn(layout, 1);
951         uiLayoutSetContextPointer(col, "constraint", &ptr);
952
953         box= uiLayoutBox(col);
954         row = uiLayoutRow(box, 0);
955         block= uiLayoutGetBlock(box);
956
957         /* Draw constraint header */
958         
959         /* rounded header */
960         rb_col= (con->flag & CONSTRAINT_ACTIVE)?50:20;
961
962         /* open/close */
963         uiBlockSetEmboss(block, UI_EMBOSSN);
964         uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NULL);
965         uiBlockSetEmboss(block, UI_EMBOSS);
966         
967         /* name */
968         uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
969
970         if (con->flag & CONSTRAINT_DISABLE)
971                 uiLayoutSetRedAlert(row, 1);
972         
973         if(proxy_protected == 0) {
974                 uiItemR(row, &ptr, "name", 0, "", ICON_NULL);
975         }
976         else
977                 uiItemL(row, con->name, ICON_NULL);
978         
979         uiLayoutSetRedAlert(row, 0);
980         
981         /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
982         if (proxy_protected) {
983                 uiBlockSetEmboss(block, UI_EMBOSSN);
984                 
985                 /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
986                 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco+244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
987                 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco+262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
988                 
989                 uiBlockSetEmboss(block, UI_EMBOSS);
990         }
991         else {
992                 short prev_proxylock, show_upbut, show_downbut;
993                 
994                 /* Up/Down buttons: 
995                  *      Proxy-constraints are not allowed to occur after local (non-proxy) constraints
996                  *      as that poses problems when restoring them, so disable the "up" button where
997                  *      it may cause this situation. 
998                  *
999                  *      Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose. 
1000                  */
1001                 if (proxylocked_constraints_owner(ob, pchan)) {
1002                         if (con->prev) {
1003                                 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
1004                         }
1005                         else
1006                                 prev_proxylock= 0;
1007                 }
1008                 else
1009                         prev_proxylock= 0;
1010                         
1011                 show_upbut= ((prev_proxylock == 0) && (con->prev));
1012                 show_downbut= (con->next) ? 1 : 0;
1013                 
1014                 /* enabled */
1015                 uiBlockSetEmboss(block, UI_EMBOSSN);
1016                 uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
1017                 uiBlockSetEmboss(block, UI_EMBOSS);
1018                 
1019                 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
1020                 
1021                 /* up/down */
1022                 if (show_upbut || show_downbut) {
1023                         uiBlockBeginAlign(block);
1024                         if (show_upbut)
1025                                 uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
1026                                 
1027                         if (show_downbut)
1028                                 uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
1029                         uiBlockEndAlign(block);
1030                 }
1031                 
1032                 /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
1033                 uiBlockSetEmboss(block, UI_EMBOSSN);
1034                 uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
1035                 uiBlockSetEmboss(block, UI_EMBOSS);
1036         }
1037
1038         /* Set but-locks for protected settings (magic numbers are used here!) */
1039         if (proxy_protected)
1040                 uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
1041
1042         /* Draw constraint data */
1043         if ((con->flag & CONSTRAINT_EXPAND) == 0) {
1044                 (yco) -= 21;
1045         }
1046         else {
1047                 box= uiLayoutBox(col);
1048                 block= uiLayoutAbsoluteBlock(box);
1049                 result= box;
1050         }
1051
1052         /* clear any locks set up for proxies/lib-linking */
1053         uiBlockClearButLock(block);
1054
1055         return result;
1056 }
1057
1058 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
1059 {
1060         Object *ob;
1061         bConstraint *con;
1062
1063         /* verify we have valid data */
1064         if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
1065                 printf("uiTemplateConstraint: expected constraint on object.\n");
1066                 return NULL;
1067         }
1068
1069         ob= ptr->id.data;
1070         con= ptr->data;
1071
1072         if(!ob || !(GS(ob->id.name) == ID_OB)) {
1073                 printf("uiTemplateConstraint: expected constraint on object.\n");
1074                 return NULL;
1075         }
1076         
1077         uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
1078
1079         /* hrms, the temporal constraint should not draw! */
1080         if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
1081                 bKinematicConstraint *data= con->data;
1082                 if(data->flag & CONSTRAINT_IK_TEMP)
1083                         return NULL;
1084         }
1085
1086         return draw_constraint(layout, ob, con);
1087 }
1088
1089
1090 /************************* Preview Template ***************************/
1091
1092 #include "DNA_lamp_types.h"
1093 #include "DNA_material_types.h"
1094 #include "DNA_world_types.h"
1095
1096 #define B_MATPRV 1
1097
1098 static void do_preview_buttons(bContext *C, void *arg, int event)
1099 {
1100         switch(event) {
1101                 case B_MATPRV:
1102                         WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
1103                         break;
1104         }
1105 }
1106
1107 void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, MTex *slot)
1108 {
1109         uiLayout *row, *col;
1110         uiBlock *block;
1111         Material *ma= NULL;
1112         Tex *tex = (Tex*)id;
1113         ID *pid, *pparent;
1114         short *pr_texture= NULL;
1115         PointerRNA material_ptr;
1116         PointerRNA texture_ptr;
1117
1118         if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
1119                 printf("uiTemplatePreview: expected ID of type material, texture, lamp or world.\n");
1120                 return;
1121         }
1122
1123         /* decide what to render */
1124         pid= id;
1125         pparent= NULL;
1126
1127         if(id && (GS(id->name) == ID_TE)) {
1128                 if(parent && (GS(parent->name) == ID_MA))
1129                         pr_texture= &((Material*)parent)->pr_texture;
1130                 else if(parent && (GS(parent->name) == ID_WO))
1131                         pr_texture= &((World*)parent)->pr_texture;
1132                 else if(parent && (GS(parent->name) == ID_LA))
1133                         pr_texture= &((Lamp*)parent)->pr_texture;
1134
1135                 if(pr_texture) {
1136                         if(*pr_texture == TEX_PR_OTHER)
1137                                 pid= parent;
1138                         else if(*pr_texture == TEX_PR_BOTH)
1139                                 pparent= parent;
1140                 }
1141         }
1142
1143         /* layout */
1144         block= uiLayoutGetBlock(layout);
1145         row= uiLayoutRow(layout, 0);
1146         col= uiLayoutColumn(row, 0);
1147         uiLayoutSetKeepAspect(col, 1);
1148         
1149         /* add preview */
1150         uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
1151         uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
1152         uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
1153         
1154         /* add buttons */
1155         if (pid && show_buttons) {
1156                 if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
1157                         if(GS(pid->name) == ID_MA) ma= (Material*)pid;
1158                         else ma= (Material*)pparent;
1159                         
1160                         /* Create RNA Pointer */
1161                         RNA_pointer_create(id, &RNA_Material, ma, &material_ptr);
1162
1163                         col = uiLayoutColumn(row, 1);
1164                         uiLayoutSetScaleX(col, 1.5);
1165                         uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NULL);
1166                 }
1167
1168                 if(pr_texture) {
1169                         /* Create RNA Pointer */
1170                         RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
1171                         
1172                         uiLayoutRow(layout, 1);
1173                         uiDefButS(block, ROW, B_MATPRV, "Texture",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
1174                         if(GS(parent->name) == ID_MA)
1175                                 uiDefButS(block, ROW, B_MATPRV, "Material",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1176                         else if(GS(parent->name) == ID_LA)
1177                                 uiDefButS(block, ROW, B_MATPRV, "Lamp",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1178                         else if(GS(parent->name) == ID_WO)
1179                                 uiDefButS(block, ROW, B_MATPRV, "World",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1180                         uiDefButS(block, ROW, B_MATPRV, "Both",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
1181                         
1182                         /* Alpha buton for texture preview */
1183                         if(*pr_texture!=TEX_PR_OTHER) {
1184                                 row = uiLayoutRow(layout, 0);
1185                                 uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NULL);
1186                         }
1187                 }
1188         }
1189 }
1190
1191 /********************** ColorRamp Template **************************/
1192
1193
1194 typedef struct RNAUpdateCb {
1195         PointerRNA ptr;
1196         PropertyRNA *prop;
1197 } RNAUpdateCb;
1198
1199 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
1200 {
1201         RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
1202
1203         /* we call update here on the pointer property, this way the
1204            owner of the curve mapping can still define it's own update
1205            and notifier, even if the CurveMapping struct is shared. */
1206         RNA_property_update(C, &cb->ptr, cb->prop);
1207 }
1208
1209 #define B_BANDCOL 1
1210
1211 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
1212 {
1213         ColorBand *coba= coba_v;
1214         float pos= 0.5f;
1215
1216         if(coba->tot > 1) {
1217                 if(coba->cur > 0)       pos= (coba->data[coba->cur-1].pos + coba->data[coba->cur].pos) * 0.5f;
1218                 else                            pos= (coba->data[coba->cur+1].pos + coba->data[coba->cur].pos) * 0.5f;
1219         }
1220
1221         if(colorband_element_add(coba, pos)) {
1222                 rna_update_cb(C, cb_v, NULL);
1223                 ED_undo_push(C, "Add colorband");       
1224         }
1225 }
1226
1227 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
1228 {
1229         ColorBand *coba= coba_v;
1230
1231         if(colorband_element_remove(coba, coba->cur)) {
1232                 ED_undo_push(C, "Delete colorband");
1233                 rna_update_cb(C, cb_v, NULL);
1234         }
1235 }
1236
1237 static void colorband_flip_cb(bContext *C, void *cb_v, void *coba_v)
1238 {
1239         CBData data_tmp[MAXCOLORBAND];
1240
1241         ColorBand *coba= coba_v;
1242         int a;
1243
1244         for(a=0; a<coba->tot; a++) {
1245                 data_tmp[a]= coba->data[coba->tot - (a + 1)];
1246         }
1247         for(a=0; a<coba->tot; a++) {
1248                 data_tmp[a].pos = 1.0f - data_tmp[a].pos;
1249                 coba->data[a]= data_tmp[a];
1250         }
1251
1252         /* may as well flip the cur*/
1253         coba->cur= coba->tot - (coba->cur + 1);
1254
1255         ED_undo_push(C, "Flip colorband");
1256
1257         rna_update_cb(C, cb_v, NULL);
1258 }
1259
1260
1261 /* offset aligns from bottom, standard width 300, height 115 */
1262 static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
1263 {
1264         
1265         uiBut *bt;
1266         uiLayout *row;
1267
1268         if(coba==NULL) return;
1269
1270         bt= uiDefBut(block, BUT, 0,     "Add",                  0+xoffs,100+yoffs,40,20, 0, 0, 0, 0, 0, "Add a new color stop to the colorband");
1271         uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1272
1273         bt= uiDefBut(block, BUT, 0,     "Delete",               45+xoffs,100+yoffs,45,20, 0, 0, 0, 0, 0, "Delete the active position");
1274         uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1275
1276
1277         /* XXX, todo for later - convert to operator - campbell */
1278         bt= uiDefBut(block, BUT, 0,     "F",            95+xoffs,100+yoffs,20,20, 0, 0, 0, 0, 0, "Flip colorband");
1279         uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1280
1281         uiDefButS(block, NUM, 0,                "",                             120+xoffs,100+yoffs,80, 20, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, "Choose active color stop");
1282
1283         bt= uiDefButS(block, MENU, 0,           "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1284                         210+xoffs, 100+yoffs, 90, 20,           &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1285         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1286         uiBlockEndAlign(block);
1287
1288         bt= uiDefBut(block, BUT_COLORBAND, 0, "",       xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, "");
1289         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1290
1291
1292
1293         if(coba->tot) {
1294                 CBData *cbd= coba->data + coba->cur;
1295
1296                 /* better to use rna so we can animate them */
1297                 PointerRNA ptr;
1298                 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1299                 row= uiLayoutRow(layout, 0);
1300                 uiItemR(row, &ptr, "position", 0, "Pos", ICON_NULL);
1301                 uiItemR(row, &ptr, "color", 0, "", ICON_NULL);
1302         }
1303
1304 }
1305
1306 static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
1307 {
1308         uiBut *bt;
1309         float unit= (butr->xmax-butr->xmin)/14.0f;
1310         float xs= butr->xmin;
1311
1312         uiBlockBeginAlign(block);
1313         bt= uiDefBut(block, BUT, 0,     "Add",                  xs,butr->ymin+20.0f,2.0f*unit,20,       NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
1314         uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1315         bt= uiDefBut(block, BUT, 0,     "Delete",               xs+2.0f*unit,butr->ymin+20.0f,1.5f*unit,20,     NULL, 0, 0, 0, 0, "Delete the active position");
1316         uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1317         bt= uiDefBut(block, BUT, 0,     "F",            xs+3.5f*unit,butr->ymin+20.0f,0.5f*unit,20,     NULL, 0, 0, 0, 0, "Flip the color ramp");
1318         uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1319         uiBlockEndAlign(block);
1320
1321         if(coba->tot) {
1322                 CBData *cbd= coba->data + coba->cur;
1323                 PointerRNA ptr;
1324                 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1325                 uiItemR(layout, &ptr, "color", 0, "", ICON_NULL);
1326         }
1327
1328         bt= uiDefButS(block, MENU, 0,           "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1329                         xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20,            &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1330         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1331
1332         bt= uiDefBut(block, BUT_COLORBAND, 0, "",               xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, "");
1333         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1334
1335         uiBlockEndAlign(block);
1336 }
1337
1338 static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
1339 {
1340         if(small)
1341                 colorband_buttons_small(layout, block, coba, butr, cb);
1342         else
1343                 colorband_buttons_large(layout, block, coba, 0, 0, cb);
1344 }
1345
1346 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, int expand)
1347 {
1348         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1349         PointerRNA cptr;
1350         RNAUpdateCb *cb;
1351         uiBlock *block;
1352         rctf rect;
1353
1354         if(!prop || RNA_property_type(prop) != PROP_POINTER)
1355                 return;
1356
1357         cptr= RNA_property_pointer_get(ptr, prop);
1358         if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
1359                 return;
1360
1361         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1362         cb->ptr= *ptr;
1363         cb->prop= prop;
1364
1365         rect.xmin= 0; rect.xmax= 200;
1366         rect.ymin= 0; rect.ymax= 190;
1367
1368         block= uiLayoutAbsoluteBlock(layout);
1369         colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1370
1371         MEM_freeN(cb);
1372 }
1373
1374 /********************* Histogram Template ************************/
1375
1376 void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname)
1377 {
1378         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1379         PointerRNA cptr;
1380         RNAUpdateCb *cb;
1381         uiBlock *block;
1382         uiBut *bt;
1383         Histogram *hist;
1384         rctf rect;
1385         
1386         if(!prop || RNA_property_type(prop) != PROP_POINTER)
1387                 return;
1388         
1389         cptr= RNA_property_pointer_get(ptr, prop);
1390         if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram))
1391                 return;
1392         
1393         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1394         cb->ptr= *ptr;
1395         cb->prop= prop;
1396         
1397         rect.xmin= 0; rect.xmax= 200;
1398         rect.ymin= 0; rect.ymax= 190;
1399         
1400         block= uiLayoutAbsoluteBlock(layout);
1401         //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1402
1403         hist = (Histogram *)cptr.data;
1404
1405         hist->height= (hist->height<=20)?20:hist->height;
1406
1407         bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, "");
1408         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1409
1410         MEM_freeN(cb);
1411 }
1412
1413 /********************* Waveform Template ************************/
1414
1415 void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
1416 {
1417         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1418         PointerRNA cptr;
1419         RNAUpdateCb *cb;
1420         uiBlock *block;
1421         uiBut *bt;
1422         Scopes *scopes;
1423         rctf rect;
1424         
1425         if(!prop || RNA_property_type(prop) != PROP_POINTER)
1426                 return;
1427         
1428         cptr= RNA_property_pointer_get(ptr, prop);
1429         if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1430                 return;
1431         scopes = (Scopes *)cptr.data;
1432         
1433         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1434         cb->ptr= *ptr;
1435         cb->prop= prop;
1436         
1437         rect.xmin= 0; rect.xmax= 200;
1438         rect.ymin= 0; rect.ymax= 190;
1439         
1440         block= uiLayoutAbsoluteBlock(layout);
1441         
1442         scopes->wavefrm_height= (scopes->wavefrm_height<=20)?20:scopes->wavefrm_height;
1443
1444         bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
1445         
1446         MEM_freeN(cb);
1447 }
1448
1449 /********************* Vectorscope Template ************************/
1450
1451 void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propname)
1452 {
1453         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1454         PointerRNA cptr;
1455         RNAUpdateCb *cb;
1456         uiBlock *block;
1457         uiBut *bt;
1458         Scopes *scopes;
1459         rctf rect;
1460         
1461         if(!prop || RNA_property_type(prop) != PROP_POINTER)
1462                 return;
1463         
1464         cptr= RNA_property_pointer_get(ptr, prop);
1465         if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1466                 return;
1467         scopes = (Scopes *)cptr.data;
1468
1469         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1470         cb->ptr= *ptr;
1471         cb->prop= prop;
1472         
1473         rect.xmin= 0; rect.xmax= 200;
1474         rect.ymin= 0; rect.ymax= 190;
1475         
1476         block= uiLayoutAbsoluteBlock(layout);
1477
1478         scopes->vecscope_height= (scopes->vecscope_height<=20)?20:scopes->vecscope_height;
1479         
1480         bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
1481         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1482         
1483         MEM_freeN(cb);
1484 }
1485
1486 /********************* CurveMapping Template ************************/
1487
1488
1489 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(arg))
1490 {
1491         CurveMapping *cumap = cumap_v;
1492         float d;
1493
1494         /* we allow 20 times zoom */
1495         if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1496                 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
1497                 cumap->curr.xmin+= d;
1498                 cumap->curr.xmax-= d;
1499                 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
1500                 cumap->curr.ymin+= d;
1501                 cumap->curr.ymax-= d;
1502         }
1503
1504         ED_region_tag_redraw(CTX_wm_region(C));
1505 }
1506
1507 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(unused))
1508 {
1509         CurveMapping *cumap = cumap_v;
1510         float d, d1;
1511
1512         /* we allow 20 times zoom, but dont view outside clip */
1513         if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1514                 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
1515
1516                 if(cumap->flag & CUMA_DO_CLIP) 
1517                         if(cumap->curr.xmin-d < cumap->clipr.xmin)
1518                                 d1= cumap->curr.xmin - cumap->clipr.xmin;
1519                 cumap->curr.xmin-= d1;
1520
1521                 d1= d;
1522                 if(cumap->flag & CUMA_DO_CLIP) 
1523                         if(cumap->curr.xmax+d > cumap->clipr.xmax)
1524                                 d1= -cumap->curr.xmax + cumap->clipr.xmax;
1525                 cumap->curr.xmax+= d1;
1526
1527                 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
1528
1529                 if(cumap->flag & CUMA_DO_CLIP) 
1530                         if(cumap->curr.ymin-d < cumap->clipr.ymin)
1531                                 d1= cumap->curr.ymin - cumap->clipr.ymin;
1532                 cumap->curr.ymin-= d1;
1533
1534                 d1= d;
1535                 if(cumap->flag & CUMA_DO_CLIP) 
1536                         if(cumap->curr.ymax+d > cumap->clipr.ymax)
1537                                 d1= -cumap->curr.ymax + cumap->clipr.ymax;
1538                 cumap->curr.ymax+= d1;
1539         }
1540
1541         ED_region_tag_redraw(CTX_wm_region(C));
1542 }
1543
1544 static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *UNUSED(arg))
1545 {
1546         CurveMapping *cumap = cumap_v;
1547
1548         curvemapping_changed(cumap, 0);
1549 }       
1550
1551 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
1552 {
1553         CurveMapping *cumap = cumap_v;
1554
1555         curvemap_remove(cumap->cm+cumap->cur, SELECT);
1556         curvemapping_changed(cumap, 0);
1557
1558         rna_update_cb(C, cb_v, NULL);
1559 }
1560
1561 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
1562 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
1563 {
1564         CurveMapping *cumap = cumap_v;
1565         uiBlock *block;
1566         uiBut *bt;
1567
1568         block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
1569
1570         /* use this for a fake extra empy space around the buttons */
1571         uiDefBut(block, LABEL, 0, "",                   -4, 16, 128, 106, NULL, 0, 0, 0, 0, "");
1572
1573         bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",    
1574                         0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, "");
1575         uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
1576
1577         uiBlockBeginAlign(block);
1578         uiDefButF(block, NUM, 0, "Min X ",       0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
1579         uiDefButF(block, NUM, 0, "Min Y ",       0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
1580         uiDefButF(block, NUM, 0, "Max X ",       0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
1581         uiDefButF(block, NUM, 0, "Max Y ",       0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
1582
1583         uiBlockSetDirection(block, UI_RIGHT);
1584
1585         uiEndBlock(C, block);
1586         return block;
1587 }
1588
1589 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
1590 {
1591         CurveMapping *cumap = cumap_v;
1592         CurveMap *cuma= cumap->cm+cumap->cur;
1593
1594         switch(event) {
1595                 case 0: /* reset */
1596                         curvemap_reset(cuma, &cumap->clipr,     cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1597                         curvemapping_changed(cumap, 0);
1598                         break;
1599                 case 1:
1600                         cumap->curr= cumap->clipr;
1601                         break;
1602                 case 2: /* set vector */
1603                         curvemap_sethandle(cuma, 1);
1604                         curvemapping_changed(cumap, 0);
1605                         break;
1606                 case 3: /* set auto */
1607                         curvemap_sethandle(cuma, 0);
1608                         curvemapping_changed(cumap, 0);
1609                         break;
1610                 case 4: /* extend horiz */
1611                         cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1612                         curvemapping_changed(cumap, 0);
1613                         break;
1614                 case 5: /* extend extrapolate */
1615                         cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
1616                         curvemapping_changed(cumap, 0);
1617                         break;
1618         }
1619         ED_region_tag_redraw(CTX_wm_region(C));
1620 }
1621
1622 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1623 {
1624         uiBlock *block;
1625         short yco= 0, menuwidth=120;
1626
1627         block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1628         uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1629
1630         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View",                             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
1631         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
1632         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
1633         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
1634         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated",    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
1635         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
1636
1637         uiBlockSetDirection(block, UI_RIGHT);
1638         uiTextBoundsBlock(block, 50);
1639
1640         uiEndBlock(C, block);
1641         return block;
1642 }
1643
1644 static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1645 {
1646         uiBlock *block;
1647         short yco= 0, menuwidth=120;
1648
1649         block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1650         uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1651
1652         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View",                             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
1653         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
1654         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
1655         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
1656
1657         uiBlockSetDirection(block, UI_RIGHT);
1658         uiTextBoundsBlock(block, 50);
1659
1660         uiEndBlock(C, block);
1661         return block;
1662 }
1663
1664 static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
1665 {
1666         ED_region_tag_redraw(CTX_wm_region(C));
1667 }
1668
1669 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
1670 {
1671         CurveMapping *cumap = cumap_v;
1672         int a;
1673         
1674         cumap->preset = CURVE_PRESET_LINE;
1675         for(a=0; a<CM_TOT; a++)
1676                 curvemap_reset(cumap->cm+a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1677         
1678         cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
1679         cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
1680         curvemapping_set_black_white(cumap, NULL, NULL);
1681         
1682         curvemapping_changed(cumap, 0);
1683
1684         rna_update_cb(C, cb_v, NULL);
1685 }
1686
1687 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
1688 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb)
1689 {
1690         CurveMapping *cumap= ptr->data;
1691         uiLayout *row, *sub, *split;
1692         uiBlock *block;
1693         uiBut *bt;
1694         float dx= UI_UNIT_X;
1695         int icon, size;
1696         int bg=-1;
1697
1698         block= uiLayoutGetBlock(layout);
1699
1700         /* curve chooser */
1701         row= uiLayoutRow(layout, 0);
1702
1703         if(labeltype=='v') {
1704                 /* vector */
1705                 sub= uiLayoutRow(row, 1);
1706                 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1707
1708                 if(cumap->cm[0].curve) {
1709                         bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1710                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1711                 }
1712                 if(cumap->cm[1].curve) {
1713                         bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1714                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1715                 }
1716                 if(cumap->cm[2].curve) {
1717                         bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1718                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1719                 }
1720         }
1721         else if(labeltype=='c') {
1722                 /* color */
1723                 sub= uiLayoutRow(row, 1);
1724                 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1725
1726                 if(cumap->cm[3].curve) {
1727                         bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
1728                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1729                 }
1730                 if(cumap->cm[0].curve) {
1731                         bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1732                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1733                 }
1734                 if(cumap->cm[1].curve) {
1735                         bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1736                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1737                 }
1738                 if(cumap->cm[2].curve) {
1739                         bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1740                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1741                 }
1742         }
1743         else if (labeltype == 'h') {
1744                 /* HSV */
1745                 sub= uiLayoutRow(row, 1);
1746                 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1747                 
1748                 if(cumap->cm[0].curve) {
1749                         bt= uiDefButI(block, ROW, 0, "H", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1750                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1751                 }
1752                 if(cumap->cm[1].curve) {
1753                         bt= uiDefButI(block, ROW, 0, "S", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1754                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1755                 }
1756                 if(cumap->cm[2].curve) {
1757                         bt= uiDefButI(block, ROW, 0, "V", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1758                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1759                 }
1760         }
1761         else
1762                 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
1763         
1764         if (labeltype=='h')
1765                 bg = UI_GRAD_H;
1766
1767         /* operation buttons */
1768         sub= uiLayoutRow(row, 1);
1769
1770         uiBlockSetEmboss(block, UI_EMBOSSN);
1771
1772         bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
1773         uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
1774
1775         bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
1776         uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
1777
1778         if(brush)
1779                 bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools");
1780         else
1781                 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools");
1782
1783         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1784
1785         if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1786         bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, 18, "Clipping Options");
1787         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1788
1789         bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
1790         uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
1791
1792         uiBlockSetEmboss(block, UI_EMBOSS);
1793
1794         uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
1795
1796         /* curve itself */
1797         size= uiLayoutGetWidth(layout);
1798         row= uiLayoutRow(layout, 0);
1799         uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, "");
1800
1801         /* black/white levels */
1802         if(levels) {
1803                 split= uiLayoutSplit(layout, 0, 0);
1804                 uiItemR(uiLayoutColumn(split, 0), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NULL);
1805                 uiItemR(uiLayoutColumn(split, 0), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NULL);
1806
1807                 uiLayoutRow(layout, 0);
1808                 bt=uiDefBut(block, BUT, 0, "Reset",     0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves");
1809                 uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
1810         }
1811
1812         uiBlockSetNFunc(block, NULL, NULL, NULL);
1813 }
1814
1815 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, int levels, int brush)
1816 {
1817         RNAUpdateCb *cb;
1818         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1819         PointerRNA cptr;
1820
1821         if(!prop || RNA_property_type(prop) != PROP_POINTER)
1822                 return;
1823
1824         cptr= RNA_property_pointer_get(ptr, prop);
1825         if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
1826                 return;
1827
1828         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1829         cb->ptr= *ptr;
1830         cb->prop= prop;
1831
1832         curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb);
1833
1834         MEM_freeN(cb);
1835 }
1836
1837 /********************* ColorWheel Template ************************/
1838
1839 #define WHEEL_SIZE      100
1840
1841 void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic)
1842 {
1843         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1844         uiBlock *block= uiLayoutGetBlock(layout);
1845         uiLayout *col, *row;
1846         uiBut *but;
1847         float softmin, softmax, step, precision;
1848         
1849         if (!prop) {
1850                 printf("uiTemplateColorWheel: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1851                 return;
1852         }
1853
1854         RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
1855         
1856         col = uiLayoutColumn(layout, 0);
1857         row= uiLayoutRow(col, 1);
1858         
1859         but= uiDefButR(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 0, 0, "");
1860
1861         if(lock) {
1862                 but->flag |= UI_BUT_COLOR_LOCK;
1863         }
1864
1865         if(lock_luminosity) {
1866                 float color[4]; /* incase of alpha */
1867                 but->flag |= UI_BUT_VEC_SIZE_LOCK;
1868                 RNA_property_float_get_array(ptr, prop, color);
1869                 but->a2= len_v3(color);
1870         }
1871
1872         if(cubic)
1873                 but->flag |= UI_BUT_COLOR_CUBIC;
1874
1875         uiItemS(row);
1876         
1877         if (value_slider)
1878                 uiDefButR(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, propname, -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
1879 }
1880
1881 /********************* Layer Buttons Template ************************/
1882
1883 static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
1884 {
1885         uiBut *but = arg1;
1886         int cur = GET_INT_FROM_POINTER(arg2);
1887         wmWindow *win= CTX_wm_window(C);
1888         int i, tot, shift= win->eventstate->shift;
1889
1890         if(!shift) {
1891                 tot= RNA_property_array_length(&but->rnapoin, but->rnaprop);
1892                 
1893                 /* Normally clicking only selects one layer */
1894                 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, 1);
1895                 for(i = 0; i < tot; ++i) {
1896                         if(i != cur)
1897                                 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, 0);
1898                 }
1899         }
1900 }
1901
1902 // TODO:
1903 //      - for now, grouping of layers is determined by dividing up the length of 
1904 //        the array of layer bitflags
1905
1906 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
1907                           PointerRNA *used_ptr, const char *used_propname, int active_layer)
1908 {
1909         uiLayout *uRow, *uCol;
1910         PropertyRNA *prop, *used_prop= NULL;
1911         int groups, cols, layers;
1912         int group, col, layer, row;
1913         int cols_per_group = 5;
1914
1915         prop= RNA_struct_find_property(ptr, propname);
1916         if (!prop) {
1917                 printf("uiTemplateLayer: layers property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1918                 return;
1919         }
1920         
1921         /* the number of layers determines the way we group them 
1922          *      - we want 2 rows only (for now)
1923          *      - the number of columns (cols) is the total number of buttons per row
1924          *        the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
1925          *      - for now, only split into groups if group will have at least 5 items
1926          */
1927         layers= RNA_property_array_length(ptr, prop);
1928         cols= (layers / 2) + (layers % 2);
1929         groups= ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
1930
1931         if(used_ptr && used_propname) {
1932                 used_prop= RNA_struct_find_property(used_ptr, used_propname);
1933                 if (!used_prop) {
1934                         printf("uiTemplateLayer: used layers property not found: %s.%s\n", RNA_struct_identifier(ptr->type), used_propname);
1935                         return;
1936                 }
1937
1938                 if(RNA_property_array_length(used_ptr, used_prop) < layers)
1939                         used_prop = NULL;
1940         }
1941         
1942         /* layers are laid out going across rows, with the columns being divided into groups */
1943         
1944         for (group= 0; group < groups; group++) {
1945                 uCol= uiLayoutColumn(layout, 1);
1946                 
1947                 for (row= 0; row < 2; row++) {
1948                         uiBlock *block;
1949                         uiBut *but;
1950
1951                         uRow= uiLayoutRow(uCol, 1);
1952                         block= uiLayoutGetBlock(uRow);
1953                         layer= groups*cols_per_group*row + cols_per_group*group;
1954                         
1955                         /* add layers as toggle buts */
1956                         for (col= 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
1957                                 int icon = 0;
1958                                 int butlay = 1 << layer;
1959
1960                                 if(active_layer & butlay)
1961                                         icon = ICON_LAYER_ACTIVE;
1962                                 else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer))
1963                                         icon = ICON_LAYER_USED;
1964                                 
1965                                 but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, 10, 10);
1966                                 uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
1967                                 but->type= TOG;
1968                         }
1969                 }
1970         }
1971 }
1972
1973
1974 /************************* List Template **************************/
1975
1976 static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
1977 {
1978         ID *id= NULL;
1979         int icon;
1980
1981         if(!itemptr->data)
1982                 return rnaicon;
1983
1984         /* try ID, material or texture slot */
1985         if(RNA_struct_is_ID(itemptr->type)) {
1986                 id= itemptr->id.data;
1987         }
1988         else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
1989                 id= RNA_pointer_get(itemptr, "material").data;
1990         }
1991         else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
1992                 id= RNA_pointer_get(itemptr, "texture").data;
1993         }
1994
1995         /* get icon from ID */
1996         if(id) {
1997                 icon= ui_id_icon_get(C, id, big);
1998
1999                 if(icon)
2000                         return icon;
2001         }
2002
2003         return rnaicon;
2004 }
2005
2006 static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, const char *activepropname)
2007 {
2008         uiBlock *block= uiLayoutGetBlock(layout);
2009         uiBut *but;
2010         uiLayout *split, *overlap, *sub, *row;
2011         char *namebuf;
2012         const char *name;
2013         int icon;
2014
2015         overlap= uiLayoutOverlap(layout);
2016
2017         /* list item behind label & other buttons */
2018         sub= uiLayoutRow(overlap, 0);
2019
2020         but= uiDefButR(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
2021         uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2022
2023         sub= uiLayoutRow(overlap, 0);
2024
2025         /* retrieve icon and name */
2026         icon= list_item_icon_get(C, itemptr, rnaicon, 0);
2027         if(icon == ICON_NULL || icon == ICON_DOT)
2028                 icon= 0;
2029
2030         namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0);
2031         name= (namebuf)? namebuf: "";
2032
2033         /* hardcoded types */
2034         if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
2035                 uiItemL(sub, name, icon);
2036                 uiBlockSetEmboss(block, UI_EMBOSSN);
2037                 uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
2038                 uiBlockSetEmboss(block, UI_EMBOSS);
2039         }
2040         else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
2041                 uiItemL(sub, name, icon);
2042                 uiBlockSetEmboss(block, UI_EMBOSS);
2043                 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0,  NULL);
2044         }
2045         else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
2046                 uiItemL(sub, name, icon);
2047                 uiBlockSetEmboss(block, UI_EMBOSS);
2048                 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0,  NULL);
2049         }
2050         else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2051                 /* provision to draw active node name */
2052                 Material *ma, *manode;
2053                 Object *ob= (Object*)ptr->id.data;
2054                 int index= (Material**)itemptr->data - ob->mat;
2055                 
2056                 /* default item with material base name */
2057                 uiItemL(sub, name, icon);
2058                 
2059                 ma= give_current_material(ob, index+1);
2060                 if(ma) {
2061                         manode= give_node_material(ma);
2062                         if(manode) {
2063                                 char str[MAX_ID_NAME + 12];
2064                                 sprintf(str, "Node %s", manode->id.name+2);
2065                                 uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
2066                         }
2067                         else if(ma->use_nodes) {
2068                                 uiItemL(sub, "Node <none>", ICON_NULL);
2069                         }
2070                 }
2071         }
2072         else if(itemptr->type == &RNA_ShapeKey) {
2073                 Object *ob= (Object*)activeptr->data;
2074
2075                 split= uiLayoutSplit(sub, 0.75f, 0);
2076
2077                 uiItemL(split, name, icon);
2078
2079                 uiBlockSetEmboss(block, UI_EMBOSSN);
2080                 row= uiLayoutRow(split, 1);
2081                 if(i == 0) uiItemL(row, "", ICON_NULL);
2082                 else uiItemR(row, itemptr, "value", 0, "", ICON_NULL);
2083
2084                 if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))
2085                         uiLayoutSetActive(row, 0);
2086                 //uiItemR(row, itemptr, "mute", 0, "", ICON_MUTE_IPO_OFF);
2087                 uiBlockSetEmboss(block, UI_EMBOSS);
2088         }
2089         else
2090                 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
2091
2092         /* free name */
2093         if(namebuf)
2094                 MEM_freeN(namebuf);
2095 }
2096
2097 void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, int rows, int maxrows, int listtype)
2098 {
2099         //Scene *scene= CTX_data_scene(C);
2100         PropertyRNA *prop= NULL, *activeprop;
2101         PropertyType type, activetype;
2102         StructRNA *ptype;
2103         uiLayout *box, *row, *col;
2104         uiBlock *block;
2105         uiBut *but;
2106         Panel *pa;
2107         char *name, str[32];
2108         int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
2109
2110         /* validate arguments */
2111         block= uiLayoutGetBlock(layout);
2112         pa= block->panel;
2113
2114         if(!pa) {
2115                 printf("uiTemplateList: only works inside a panel.\n");
2116                 return;
2117         }
2118
2119         if(!activeptr->data)
2120                 return;
2121         
2122         if(ptr->data) {
2123                 prop= RNA_struct_find_property(ptr, propname);
2124                 if(!prop) {
2125                         printf("uiTemplateList: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
2126                         return;
2127                 }
2128         }
2129
2130         activeprop= RNA_struct_find_property(activeptr, activepropname);
2131         if(!activeprop) {
2132                 printf("uiTemplateList: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), activepropname);
2133                 return;
2134         }
2135
2136         if(prop) {
2137                 type= RNA_property_type(prop);
2138                 if(type != PROP_COLLECTION) {
2139                         printf("uiTemplateList: expected collection property.\n");
2140                         return;
2141                 }
2142         }
2143
2144         activetype= RNA_property_type(activeprop);
2145         if(activetype != PROP_INT) {
2146                 printf("uiTemplateList: expected integer property.\n");
2147                 return;
2148         }
2149
2150         /* get icon */
2151         if(ptr->data && prop) {
2152                 ptype= RNA_property_pointer_type(ptr, prop);
2153                 rnaicon= RNA_struct_ui_icon(ptype);
2154         }
2155
2156         /* get active data */
2157         activei= RNA_property_int_get(activeptr, activeprop);
2158
2159         if(listtype == 'i') {
2160                 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2161                 col= uiLayoutColumn(box, 1);
2162                 row= uiLayoutRow(col, 0);
2163
2164                 if(ptr->data && prop) {
2165                         /* create list items */
2166                         RNA_PROP_BEGIN(ptr, itemptr, prop) {
2167                                 /* create button */
2168                                 if(i == 9)
2169                                         row= uiLayoutRow(col, 0);
2170
2171                                 icon= list_item_icon_get(C, &itemptr, rnaicon, 1);
2172                                 but= uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
2173                                 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2174                                 
2175
2176                                 i++;
2177                         }
2178                         RNA_PROP_END;
2179                 }
2180         }
2181         else if(listtype == 'c') {
2182                 /* compact layout */
2183                 found= 0;
2184
2185                 row= uiLayoutRow(layout, 1);
2186
2187                 if(ptr->data && prop) {
2188                         /* create list items */
2189                         RNA_PROP_BEGIN(ptr, itemptr, prop) {
2190                                 found= (activei == i);
2191
2192                                 if(found) {
2193                                         /* create button */
2194                                         name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
2195                                         icon= list_item_icon_get(C, &itemptr, rnaicon, 0);
2196                                         uiItemL(row, (name)? name: "", icon);
2197
2198                                         if(name)
2199                                                 MEM_freeN(name);
2200                                 }
2201
2202                                 i++;
2203                         }
2204                         RNA_PROP_END;
2205                 }
2206
2207                 /* if not found, add in dummy button */
2208                 if(i == 0)
2209                         uiItemL(row, "", ICON_NULL);
2210
2211                 /* next/prev button */
2212                 sprintf(str, "%d :", i);
2213                 but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activepropname, 0, 0, 0, 0, 0, "");
2214                 if(i == 0)
2215                         uiButSetFlag(but, UI_BUT_DISABLED);
2216         }
2217         else {
2218                 /* default rows */
2219                 if(rows == 0)
2220                         rows= 5;
2221                 if (maxrows == 0)
2222                         maxrows = 5;
2223                 if(pa->list_grip_size != 0)
2224                         rows= pa->list_grip_size;
2225
2226                 /* layout */
2227                 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2228                 row= uiLayoutRow(box, 0);
2229                 col = uiLayoutColumn(row, 1);
2230
2231                 /* init numbers */
2232                 RNA_property_int_range(activeptr, activeprop, &min, &max);
2233
2234                 if(prop)
2235                         len= RNA_property_collection_length(ptr, prop);
2236                 items= CLAMPIS(len, rows, MAX2(rows, maxrows));
2237
2238                 /* if list length changes and active is out of view, scroll to it */
2239                 if(pa->list_last_len != len)
2240                         if((activei < pa->list_scroll || activei >= pa->list_scroll+items))
2241                                 pa->list_scroll= activei;
2242
2243                 pa->list_scroll= MIN2(pa->list_scroll, len-items);
2244                 pa->list_scroll= MAX2(pa->list_scroll, 0);
2245                 pa->list_size= items;
2246                 pa->list_last_len= len;
2247
2248                 if(ptr->data && prop) {
2249                         /* create list items */
2250                         RNA_PROP_BEGIN(ptr, itemptr, prop) {
2251                                 if(i >= pa->list_scroll && i<pa->list_scroll+items)
2252                                         list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activepropname);
2253
2254                                 i++;
2255                         }
2256                         RNA_PROP_END;
2257                 }
2258
2259                 /* add dummy buttons to fill space */
2260                 while(i < pa->list_scroll+items) {
2261                         if(i >= pa->list_scroll)
2262                                 uiItemL(col, "", ICON_NULL);
2263                         i++;
2264                 }
2265
2266                 /* add scrollbar */
2267                 if(len > items) {
2268                         col= uiLayoutColumn(row, 0);
2269                         uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
2270                 }
2271         }
2272 }
2273
2274 /************************* Operator Search Template **************************/
2275
2276 static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
2277 {
2278         wmOperatorType *ot= arg2;
2279         
2280         if(ot)
2281                 WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
2282 }
2283
2284 static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
2285 {
2286         wmOperatorType *ot = WM_operatortype_first();
2287         
2288         for(; ot; ot= ot->next) {
2289                 
2290                 if(BLI_strcasestr(ot->name, str)) {
2291                         if(WM_operator_poll((bContext*)C, ot)) {
2292                                 char name[256];
2293                                 int len= strlen(ot->name);
2294                                 
2295                                 /* display name for menu, can hold hotkey */
2296                                 BLI_strncpy(name, ot->name, 256);
2297                                 
2298                                 /* check for hotkey */
2299                                 if(len < 256-6) {
2300                                         if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
2301                                                 name[len]= '|';
2302                                 }
2303                                 
2304                                 if(0==uiSearchItemAdd(items, name, ot, 0))
2305                                         break;
2306                         }
2307                 }
2308         }
2309 }
2310
2311 void uiTemplateOperatorSearch(uiLayout *layout)
2312 {
2313         uiBlock *block;
2314         uiBut *but;
2315         static char search[256]= "";
2316                 
2317         block= uiLayoutGetBlock(layout);
2318         uiBlockSetCurLayout(block, layout);
2319
2320         but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, "");
2321         uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
2322 }
2323
2324 /************************* Running Jobs Template **************************/
2325
2326 #define B_STOPRENDER    1
2327 #define B_STOPCAST              2
2328 #define B_STOPANIM              3
2329 #define B_STOPCOMPO             4
2330
2331 static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
2332 {
2333         switch(event) {
2334                 case B_STOPRENDER:
2335                         G.afbreek= 1;
2336                         break;
2337                 case B_STOPCAST:
2338                         WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
2339                         break;
2340                 case B_STOPANIM:
2341                         WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
2342                         break;
2343                 case B_STOPCOMPO:
2344                         WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2345                         break;
2346         }
2347 }
2348
2349 void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
2350 {
2351         bScreen *screen= CTX_wm_screen(C);
2352         wmWindowManager *wm= CTX_wm_manager(C);
2353         ScrArea *sa= CTX_wm_area(C);
2354         uiBlock *block;
2355         void *owner= NULL;
2356         int handle_event;
2357         
2358         block= uiLayoutGetBlock(layout);
2359         uiBlockSetCurLayout(block, layout);
2360
2361         uiBlockSetHandleFunc(block, do_running_jobs, NULL);
2362
2363         if(sa->spacetype==SPACE_NODE) {
2364                 if(WM_jobs_test(wm, sa))
2365                    owner = sa;
2366                 handle_event= B_STOPCOMPO;
2367         } 
2368         else {
2369                 Scene *scene;
2370                 /* another scene can be rendering too, for example via compositor */
2371                 for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next)
2372                         if(WM_jobs_test(wm, scene))
2373                                 break;
2374                 owner = scene;
2375                 handle_event= B_STOPRENDER;
2376         }
2377
2378         if(owner) {
2379                 uiLayout *ui_abs;
2380                 
2381                 ui_abs= uiLayoutAbsolute(layout, 0);
2382                 
2383                 uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, 
2384                                 0, UI_UNIT_Y*0.1, UI_UNIT_X*0.8, UI_UNIT_Y*0.8, NULL, 0.0f, 0.0f, 0, 0, "Stop this job");
2385                 uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner), 
2386                                 UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, "Progress");
2387                 
2388                 uiLayoutRow(layout, 0);
2389         }
2390         if(WM_jobs_test(wm, screen))
2391                 uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, "Capture", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
2392         if(screen->animtimer)
2393                 uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, "Anim Player", 0,0,100,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback");
2394 }
2395
2396 /************************* Reports for Last Operator Template **************************/
2397
2398 void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
2399 {
2400         ReportList *reports = CTX_wm_reports(C);
2401         Report *report= BKE_reports_last_displayable(reports);
2402         ReportTimerInfo *rti;
2403         
2404         uiLayout *ui_abs;
2405         uiBlock *block;
2406         uiBut *but;
2407         uiStyle *style= U.uistyles.first;
2408         int width;
2409         int icon=0;
2410         
2411         /* if the report display has timed out, don't show */
2412         if (!reports->reporttimer) return;
2413         
2414         rti= (ReportTimerInfo *)reports->reporttimer->customdata;
2415         
2416         if (!rti || rti->widthfac==0.0 || !report) return;
2417         
2418         ui_abs= uiLayoutAbsolute(layout, 0);
2419         block= uiLayoutGetBlock(ui_abs);
2420         
2421         width = BLF_width(style->widget.uifont_id, report->message);
2422         width = MIN2(rti->widthfac*width, width);
2423         width = MAX2(width, 10);
2424         
2425         /* make a box around the report to make it stand out */
2426         uiBlockBeginAlign(block);
2427         but= uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X+10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2428         /* set the report's bg color in but->col - ROUNDBOX feature */
2429         but->col[0]= FTOCHAR(rti->col[0]);
2430         but->col[1]= FTOCHAR(rti->col[1]);
2431         but->col[2]= FTOCHAR(rti->col[2]);
2432         but->col[3]= 255; 
2433
2434         but= uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2435         but->col[0]= but->col[1]= but->col[2]= FTOCHAR(rti->greyscale);
2436         but->col[3]= 255;
2437
2438         uiBlockEndAlign(block);
2439         
2440         
2441         /* icon and report message on top */
2442         if(report->type & RPT_ERROR_ALL)
2443                 icon = ICON_ERROR;
2444         else if(report->type & RPT_WARNING_ALL)
2445                 icon = ICON_ERROR;
2446         else if(report->type & RPT_INFO_ALL)
2447                 icon = ICON_INFO;
2448         
2449         /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report 
2450          * to be shown instead of icon when appropriate...
2451          */
2452         uiBlockSetEmboss(block, UI_EMBOSSN);
2453
2454         if (reports->list.first != reports->list.last)
2455                 uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, "Click to see rest of reports in textblock: 'Recent Reports'");
2456         else
2457                 uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2458
2459         uiBlockSetEmboss(block, UI_EMBOSS);
2460         
2461         uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2462 }
2463