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