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