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