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