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