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