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