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