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